Merge branch 'release/0.3.0'

This commit is contained in:
Sergey Abramchuk
2019-06-29 10:39:56 +03:00
1132 changed files with 91926 additions and 31597 deletions

View File

@@ -8,7 +8,7 @@ CLANG_CXX_LANGUAGE_STANDARD = gnu++14
CLANG_CXX_LIBRARY = libc++
VENDORS_DIR = $(PROJECT_DIR)/Sources/OpenVPNAdapter/Libraries/Vendors
HEADER_SEARCH_PATHS = "$(VENDORS_DIR)/asio/asio/include" "$(VENDORS_DIR)/lz4/include" "$(VENDORS_DIR)/mbedtls/include" "$(VENDORS_DIR)/openvpn"
LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*] = "$(VENDORS_DIR)/lz4/lib/sim" "$(VENDORS_DIR)/mbedtls/lib/sim"
LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*] = "$(VENDORS_DIR)/lz4/lib/ios" "$(VENDORS_DIR)/mbedtls/lib/ios"
LIBRARY_SEARCH_PATHS[sdk=iphoneos*] = "$(VENDORS_DIR)/lz4/lib/ios" "$(VENDORS_DIR)/mbedtls/lib/ios"
LIBRARY_SEARCH_PATHS[sdk=macosx*] = "$(VENDORS_DIR)/lz4/lib/macos" "$(VENDORS_DIR)/mbedtls/lib/macos"
OTHER_LDFLAGS = -lmbedtls -lmbedx509 -lmbedcrypto -llz4

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.2.0</string>
<string>0.3.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@@ -3,7 +3,7 @@ Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.name = "OpenVPNAdapter"
s.version = "0.2.0"
s.version = "0.3.0"
s.summary = "Objective-C wrapper for OpenVPN library. Compatible with iOS and macOS."
s.description = <<-DESC
OpenVPNAdapter is an Objective-C framework that allows to easily configure and establish VPN connection using OpenVPN protocol.

View File

@@ -33,7 +33,7 @@ To install OpenVPNAdapter with Cocoapods, add the following lines to your `Podfi
```ruby
target 'Your Target Name' do
use_frameworks!
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.2.0'
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.3.0'
end
```

View File

@@ -1,4 +1,4 @@
Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,4 +1,4 @@
asio version 1.12.0
Released Sunday, 04 March 2018.
asio version 1.13.0
Released Tuesday, 12 March 2019.
See doc/index.html for API documentation and a tutorial.

View File

@@ -281,7 +281,7 @@ sub copy_source_file
$line =~ s/asio::/boost::asio::/g if !$is_xsl;
print_line($output, $line, $from, $lineno);
}
elsif ($line =~ /} \/\/ namespace std/)
elsif ($line =~ /^} \/\/ namespace std/)
{
print_line($output, "} // namespace system", $from, $lineno);
print_line($output, "} // namespace boost", $from, $lineno);
@@ -365,6 +365,8 @@ sub copy_include_files
"include/asio",
"include/asio/detail",
"include/asio/detail/impl",
"include/asio/experimental",
"include/asio/experimental/impl",
"include/asio/generic",
"include/asio/generic/detail",
"include/asio/generic/detail/impl",
@@ -528,8 +530,15 @@ sub copy_examples
"src/examples/cpp11/local",
"src/examples/cpp11/multicast",
"src/examples/cpp11/nonblocking",
"src/examples/cpp11/operations",
"src/examples/cpp11/socks4",
"src/examples/cpp11/spawn",
"src/examples/cpp14/executors");
"src/examples/cpp11/ssl",
"src/examples/cpp11/timeouts",
"src/examples/cpp11/timers",
"src/examples/cpp14/executors",
"src/examples/cpp14/operations",
"src/examples/cpp17/coroutines_ts");
our $boost_dir;
foreach my $dir (@dirs)

View File

@@ -1,4 +1,4 @@
AC_INIT(asio, [1.12.0])
AC_INIT(asio, [1.13.0])
AC_CONFIG_SRCDIR(include/asio.hpp)
AM_MAINTAINER_MODE
AM_INIT_AUTOMAKE([tar-ustar])
@@ -17,20 +17,12 @@ AC_ARG_WITH(boost,
if test "${withval}" = no; then
STANDALONE="yes"
else
CPPFLAGS="$CPPFLAGS -I${withval} -DBOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING"
CPPFLAGS="$CPPFLAGS -I${withval} -DASIO_ENABLE_BOOST -DBOOST_CHRONO_HEADER_ONLY -DBOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING"
LIBS="$LIBS -L${withval}/stage/lib"
fi
],
[
BOOSTDIR=`ls -1d ../boost_*_*_*/ 2>/dev/null | sort -t "_" -k 2nr -k 3nr -k 4nr | head -n 1 | sed -e 's/\/$//'`
if test "${BOOSTDIR}" != ""; then
BOOSTDIR="`pwd`/${BOOSTDIR}"
if test -d "${BOOSTDIR}"; then
echo "using automatically detected boost from ${BOOSTDIR}"
CPPFLAGS="$CPPFLAGS -I${BOOSTDIR} -DBOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING"
LIBS="$LIBS -L${BOOSTDIR}/stage/lib"
fi
fi
STANDALONE="yes"
])
AC_ARG_ENABLE(separate-compilation,
@@ -50,6 +42,7 @@ if test "$STANDALONE" != yes; then
[
echo "Can't find boost headers. Please check the location of the boost"
echo "distribution and rerun configure using the --with-boost=DIR option."
echo "Alternatively, run with --without-boost to enable standalone build."
exit 1
],[])
fi
@@ -101,7 +94,7 @@ case $host in
WINDOWS=yes
;;
*-pc-cygwin*)
CXXFLAGS="$CXXFLAGS -D__USE_W32_SOCKETS -D_WIN32_WINNT=0x0501"
CXXFLAGS="$CXXFLAGS -D__USE_W32_SOCKETS -D_WIN32_WINNT=0x0601"
LIBS="$LIBS -lws2_32 -lmswsock"
WINDOWS=yes
;;
@@ -117,13 +110,14 @@ case $host in
CXXFLAGS="$CXXFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
;;
*-*-haiku*)
CXXFLAGS="$CXXFLAGS -lnetwork"
LDFLAGS="$LDFLAGS -lnetwork"
esac
if test "$GXX" = yes; then
CXXFLAGS="$CXXFLAGS -ftemplate-depth-256"
if test "$STANDALONE" = yes; then
CPPFLAGS="-std=c++0x $CPPFLAGS"
fi
fi
if test "$STANDALONE" = yes; then
@@ -134,6 +128,37 @@ if test "$SEPARATE_COMPILATION" = yes; then
CPPFLAGS="$CPPFLAGS -DASIO_SEPARATE_COMPILATION"
fi
AC_MSG_CHECKING([whether C++11 is enabled])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#if __cplusplus < 201103L]]
[[#error C++11 not available]]
[[#endif]])],
[AC_MSG_RESULT([yes])
HAVE_CXX11=yes;],
[AC_MSG_RESULT([no])
HAVE_CXX11=no;])
AC_MSG_CHECKING([whether C++14 is enabled])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#if __cplusplus < 201402L]]
[[#error C++14 not available]]
[[#endif]])],
[AC_MSG_RESULT([yes])
HAVE_CXX14=yes;],
[AC_MSG_RESULT([no])
HAVE_CXX14=no;])
if test "$GXX" = yes; then
if test "$STANDALONE" = yes; then
if test "$HAVE_CXX11" = no; then
HAVE_CXX11=yes
CPPFLAGS="-std=c++0x $CPPFLAGS"
fi
fi
fi
AM_CONDITIONAL(STANDALONE,test x$STANDALONE = xyes)
AM_CONDITIONAL(SEPARATE_COMPILATION,test x$SEPARATE_COMPILATION = xyes)
@@ -142,6 +167,10 @@ AM_CONDITIONAL(HAVE_BOOST_COROUTINE,test x$HAVE_BOOST_COROUTINE = xyes)
AM_CONDITIONAL(WINDOWS_TARGET,test x$WINDOWS != xno)
AM_CONDITIONAL(HAVE_CXX11,test x$HAVE_CXX11 = xyes)
AM_CONDITIONAL(HAVE_CXX14,test x$HAVE_CXX14 = xyes)
AC_OUTPUT([
Makefile
include/Makefile
@@ -149,4 +178,5 @@ AC_OUTPUT([
src/tests/Makefile
src/examples/cpp03/Makefile
src/examples/cpp11/Makefile
src/examples/cpp14/Makefile])
src/examples/cpp14/Makefile
src/examples/cpp17/Makefile])

View File

@@ -3,6 +3,7 @@ nobase_include_HEADERS = \
asio/associated_allocator.hpp \
asio/associated_executor.hpp \
asio/async_result.hpp \
asio/awaitable.hpp \
asio/basic_datagram_socket.hpp \
asio/basic_deadline_timer.hpp \
asio/basic_io_object.hpp \
@@ -27,13 +28,14 @@ nobase_include_HEADERS = \
asio/buffered_write_stream.hpp \
asio/buffer.hpp \
asio/buffers_iterator.hpp \
asio/co_spawn.hpp \
asio/completion_condition.hpp \
asio/compose.hpp \
asio/connect.hpp \
asio/coroutine.hpp \
asio/datagram_socket_service.hpp \
asio/deadline_timer.hpp \
asio/deadline_timer_service.hpp \
asio/defer.hpp \
asio/detached.hpp \
asio/detail/array_fwd.hpp \
asio/detail/array.hpp \
asio/detail/assert.hpp \
@@ -64,10 +66,12 @@ nobase_include_HEADERS = \
asio/detail/epoll_reactor.hpp \
asio/detail/eventfd_select_interrupter.hpp \
asio/detail/event.hpp \
asio/detail/executor_function.hpp \
asio/detail/executor_op.hpp \
asio/detail/fd_set_adapter.hpp \
asio/detail/fenced_block.hpp \
asio/detail/functional.hpp \
asio/detail/future.hpp \
asio/detail/gcc_arm_fenced_block.hpp \
asio/detail/gcc_hppa_fenced_block.hpp \
asio/detail/gcc_sync_fenced_block.hpp \
@@ -131,6 +135,8 @@ nobase_include_HEADERS = \
asio/detail/impl/win_thread.ipp \
asio/detail/impl/win_tss_ptr.ipp \
asio/detail/io_control.hpp \
asio/detail/io_object_executor.hpp \
asio/detail/io_object_impl.hpp \
asio/detail/is_buffer_sequence.hpp \
asio/detail/is_executor.hpp \
asio/detail/keyword_tss_ptr.hpp \
@@ -140,6 +146,7 @@ nobase_include_HEADERS = \
asio/detail/macos_fenced_block.hpp \
asio/detail/memory.hpp \
asio/detail/mutex.hpp \
asio/detail/non_const_lvalue.hpp \
asio/detail/noncopyable.hpp \
asio/detail/null_event.hpp \
asio/detail/null_fenced_block.hpp \
@@ -284,8 +291,8 @@ nobase_include_HEADERS = \
asio/error_code.hpp \
asio/error.hpp \
asio/execution_context.hpp \
asio/executor_work_guard.hpp \
asio/executor.hpp \
asio/executor_work_guard.hpp \
asio/generic/basic_endpoint.hpp \
asio/generic/datagram_protocol.hpp \
asio/generic/detail/endpoint.hpp \
@@ -296,13 +303,16 @@ nobase_include_HEADERS = \
asio/handler_alloc_hook.hpp \
asio/handler_continuation_hook.hpp \
asio/handler_invoke_hook.hpp \
asio/handler_type.hpp \
asio/high_resolution_timer.hpp \
asio.hpp \
asio/impl/awaitable.hpp \
asio/impl/buffered_read_stream.hpp \
asio/impl/buffered_write_stream.hpp \
asio/impl/co_spawn.hpp \
asio/impl/compose.hpp \
asio/impl/connect.hpp \
asio/impl/defer.hpp \
asio/impl/detached.hpp \
asio/impl/dispatch.hpp \
asio/impl/error_code.ipp \
asio/impl/error.ipp \
@@ -317,6 +327,7 @@ nobase_include_HEADERS = \
asio/impl/read_at.hpp \
asio/impl/read.hpp \
asio/impl/read_until.hpp \
asio/impl/redirect_error.hpp \
asio/impl/serial_port_base.hpp \
asio/impl/serial_port_base.ipp \
asio/impl/spawn.hpp \
@@ -327,13 +338,14 @@ nobase_include_HEADERS = \
asio/impl/system_executor.hpp \
asio/impl/thread_pool.hpp \
asio/impl/thread_pool.ipp \
asio/impl/use_awaitable.hpp \
asio/impl/use_future.hpp \
asio/impl/write_at.hpp \
asio/impl/write.hpp \
asio/io_context_strand.hpp \
asio/io_context.hpp \
asio/io_service_strand.hpp \
asio/io_context_strand.hpp \
asio/io_service.hpp \
asio/io_service_strand.hpp \
asio/ip/address.hpp \
asio/ip/address_v4.hpp \
asio/ip/address_v4_iterator.hpp \
@@ -370,7 +382,6 @@ nobase_include_HEADERS = \
asio/ip/network_v6.hpp \
asio/ip/resolver_base.hpp \
asio/ip/resolver_query_base.hpp \
asio/ip/resolver_service.hpp \
asio/ip/tcp.hpp \
asio/ip/udp.hpp \
asio/ip/unicast.hpp \
@@ -388,22 +399,17 @@ nobase_include_HEADERS = \
asio/placeholders.hpp \
asio/posix/basic_descriptor.hpp \
asio/posix/basic_stream_descriptor.hpp \
asio/posix/descriptor.hpp \
asio/posix/descriptor_base.hpp \
asio/posix/descriptor.hpp \
asio/posix/stream_descriptor.hpp \
asio/posix/stream_descriptor_service.hpp \
asio/post.hpp \
asio/raw_socket_service.hpp \
asio/read_at.hpp \
asio/read.hpp \
asio/read_until.hpp \
asio/seq_packet_socket_service.hpp \
asio/redirect_error.hpp \
asio/serial_port_base.hpp \
asio/serial_port.hpp \
asio/serial_port_service.hpp \
asio/signal_set.hpp \
asio/signal_set_service.hpp \
asio/socket_acceptor_service.hpp \
asio/socket_base.hpp \
asio/spawn.hpp \
asio/ssl/context_base.hpp \
@@ -437,11 +443,11 @@ nobase_include_HEADERS = \
asio/steady_timer.hpp \
asio/strand.hpp \
asio/streambuf.hpp \
asio/stream_socket_service.hpp \
asio/system_context.hpp \
asio/system_error.hpp \
asio/system_executor.hpp \
asio/system_timer.hpp \
asio/this_coro.hpp \
asio/thread.hpp \
asio/thread_pool.hpp \
asio/time_traits.hpp \
@@ -454,23 +460,20 @@ nobase_include_HEADERS = \
asio/ts/socket.hpp \
asio/ts/timer.hpp \
asio/unyield.hpp \
asio/use_awaitable.hpp \
asio/use_future.hpp \
asio/uses_executor.hpp \
asio/version.hpp \
asio/waitable_timer_service.hpp \
asio/wait_traits.hpp \
asio/windows/basic_handle.hpp \
asio/windows/basic_object_handle.hpp \
asio/windows/basic_overlapped_handle.hpp \
asio/windows/basic_random_access_handle.hpp \
asio/windows/basic_stream_handle.hpp \
asio/windows/object_handle.hpp \
asio/windows/object_handle_service.hpp \
asio/windows/overlapped_handle.hpp \
asio/windows/overlapped_ptr.hpp \
asio/windows/random_access_handle.hpp \
asio/windows/random_access_handle_service.hpp \
asio/windows/stream_handle.hpp \
asio/windows/stream_handle_service.hpp \
asio/write_at.hpp \
asio/write.hpp \
asio/yield.hpp

View File

@@ -2,7 +2,7 @@
// asio.hpp
// ~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,6 +18,7 @@
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/async_result.hpp"
#include "asio/awaitable.hpp"
#include "asio/basic_datagram_socket.hpp"
#include "asio/basic_deadline_timer.hpp"
#include "asio/basic_io_object.hpp"
@@ -25,6 +26,7 @@
#include "asio/basic_seq_packet_socket.hpp"
#include "asio/basic_serial_port.hpp"
#include "asio/basic_signal_set.hpp"
#include "asio/basic_socket.hpp"
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
#include "asio/basic_socket_streambuf.hpp"
@@ -40,13 +42,14 @@
#include "asio/buffered_write_stream_fwd.hpp"
#include "asio/buffered_write_stream.hpp"
#include "asio/buffers_iterator.hpp"
#include "asio/co_spawn.hpp"
#include "asio/completion_condition.hpp"
#include "asio/compose.hpp"
#include "asio/connect.hpp"
#include "asio/coroutine.hpp"
#include "asio/datagram_socket_service.hpp"
#include "asio/deadline_timer_service.hpp"
#include "asio/deadline_timer.hpp"
#include "asio/defer.hpp"
#include "asio/detached.hpp"
#include "asio/dispatch.hpp"
#include "asio/error.hpp"
#include "asio/error_code.hpp"
@@ -61,7 +64,6 @@
#include "asio/handler_alloc_hook.hpp"
#include "asio/handler_continuation_hook.hpp"
#include "asio/handler_invoke_hook.hpp"
#include "asio/handler_type.hpp"
#include "asio/high_resolution_timer.hpp"
#include "asio/io_context.hpp"
#include "asio/io_context_strand.hpp"
@@ -74,6 +76,8 @@
#include "asio/ip/address_v6.hpp"
#include "asio/ip/address_v6_iterator.hpp"
#include "asio/ip/address_v6_range.hpp"
#include "asio/ip/network_v4.hpp"
#include "asio/ip/network_v6.hpp"
#include "asio/ip/bad_address_cast.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver.hpp"
@@ -85,7 +89,6 @@
#include "asio/ip/multicast.hpp"
#include "asio/ip/resolver_base.hpp"
#include "asio/ip/resolver_query_base.hpp"
#include "asio/ip/resolver_service.hpp"
#include "asio/ip/tcp.hpp"
#include "asio/ip/udp.hpp"
#include "asio/ip/unicast.hpp"
@@ -104,48 +107,40 @@
#include "asio/posix/descriptor.hpp"
#include "asio/posix/descriptor_base.hpp"
#include "asio/posix/stream_descriptor.hpp"
#include "asio/posix/stream_descriptor_service.hpp"
#include "asio/post.hpp"
#include "asio/raw_socket_service.hpp"
#include "asio/read.hpp"
#include "asio/read_at.hpp"
#include "asio/read_until.hpp"
#include "asio/seq_packet_socket_service.hpp"
#include "asio/redirect_error.hpp"
#include "asio/serial_port.hpp"
#include "asio/serial_port_base.hpp"
#include "asio/serial_port_service.hpp"
#include "asio/signal_set.hpp"
#include "asio/signal_set_service.hpp"
#include "asio/socket_acceptor_service.hpp"
#include "asio/socket_base.hpp"
#include "asio/steady_timer.hpp"
#include "asio/strand.hpp"
#include "asio/stream_socket_service.hpp"
#include "asio/streambuf.hpp"
#include "asio/system_context.hpp"
#include "asio/system_error.hpp"
#include "asio/system_executor.hpp"
#include "asio/system_timer.hpp"
#include "asio/this_coro.hpp"
#include "asio/thread.hpp"
#include "asio/thread_pool.hpp"
#include "asio/time_traits.hpp"
#include "asio/use_awaitable.hpp"
#include "asio/use_future.hpp"
#include "asio/uses_executor.hpp"
#include "asio/version.hpp"
#include "asio/wait_traits.hpp"
#include "asio/waitable_timer_service.hpp"
#include "asio/windows/basic_handle.hpp"
#include "asio/windows/basic_object_handle.hpp"
#include "asio/windows/basic_overlapped_handle.hpp"
#include "asio/windows/basic_random_access_handle.hpp"
#include "asio/windows/basic_stream_handle.hpp"
#include "asio/windows/object_handle.hpp"
#include "asio/windows/object_handle_service.hpp"
#include "asio/windows/overlapped_handle.hpp"
#include "asio/windows/overlapped_ptr.hpp"
#include "asio/windows/random_access_handle.hpp"
#include "asio/windows/random_access_handle_service.hpp"
#include "asio/windows/stream_handle.hpp"
#include "asio/windows/stream_handle_service.hpp"
#include "asio/write.hpp"
#include "asio/write_at.hpp"

View File

@@ -2,7 +2,7 @@
// associated_allocator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// associated_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// async_result.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,7 +17,7 @@
#include "asio/detail/config.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/handler_type.hpp"
#include "asio/detail/variadic_templates.hpp"
#include "asio/detail/push_options.hpp"
@@ -41,30 +41,15 @@ namespace asio {
* The primary template assumes that the CompletionToken is the completion
* handler.
*/
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename Signature>
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename Signature = void>
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
class async_result
{
public:
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
/// The concrete completion handler type for the specific signature.
typedef CompletionToken completion_handler_type;
/// The return type of the initiating function.
typedef void return_type;
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
// For backward compatibility, determine the concrete completion handler type
// by using the legacy handler_type trait.
typedef typename handler_type<CompletionToken, Signature>::type
completion_handler_type;
// For backward compatibility, determine the initiating function return type
// using the legacy single-parameter version of async_result.
typedef typename async_result<completion_handler_type>::type return_type;
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
/// Construct an async result from a given handler.
/**
@@ -73,11 +58,6 @@ public:
* then returned from the initiating function.
*/
explicit async_result(completion_handler_type& h)
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
// No data members to initialise.
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
: legacy_result_(h)
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
{
(void)h;
}
@@ -85,56 +65,60 @@ public:
/// Obtain the value to be returned from the initiating function.
return_type get()
{
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
// Nothing to do.
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
return legacy_result_.get();
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
}
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|| defined(GENERATING_DOCUMENTATION)
/// Initiate the asynchronous operation that will produce the result, and
/// obtain the value to be returned from the initiating function.
template <typename Initiation, typename RawCompletionToken, typename... Args>
static return_type initiate(
ASIO_MOVE_ARG(Initiation) initiation,
ASIO_MOVE_ARG(RawCompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(RawCompletionToken)(token),
ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)
template <typename Initiation, typename RawCompletionToken>
static return_type initiate(
ASIO_MOVE_ARG(Initiation) initiation,
ASIO_MOVE_ARG(RawCompletionToken) token)
{
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(RawCompletionToken)(token));
}
#define ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename Initiation, typename RawCompletionToken, \
ASIO_VARIADIC_TPARAMS(n)> \
static return_type initiate( \
ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_MOVE_ARG(RawCompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
ASIO_MOVE_CAST(Initiation)(initiation)( \
ASIO_MOVE_CAST(RawCompletionToken)(token), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
#undef ASIO_PRIVATE_INITIATE_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)
private:
async_result(const async_result&) ASIO_DELETED;
async_result& operator=(const async_result&) ASIO_DELETED;
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
// No data members.
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
async_result<completion_handler_type> legacy_result_;
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
};
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use two-parameter version of async_result.) An interface for
/// customising the behaviour of an initiating function.
/**
* This template may be specialised for user-defined handler types.
*/
template <typename Handler>
class async_result<Handler>
{
public:
/// The return type of the initiating function.
typedef void type;
/// Construct an async result from a given handler.
/**
* When using a specalised async_result, the constructor has an opportunity
* to initialise some state associated with the handler, which is then
* returned from the initiating function.
*/
explicit async_result(Handler&)
{
}
/// Obtain the value to be returned from the initiating function.
type get()
{
}
};
#endif // !defined(ASIO_NO_DEPRECATED)
/// Helper template to deduce the handler type from a CompletionToken, capture
/// a local copy of the handler, and then create an async_result for the
/// handler.
@@ -194,10 +178,40 @@ struct async_result_helper
{
};
} // namespace detail
} // namespace asio
struct async_result_memfns_base
{
void initiate();
};
#include "asio/detail/pop_options.hpp"
template <typename T>
struct async_result_memfns_derived
: T, async_result_memfns_base
{
};
template <typename T, T>
struct async_result_memfns_check
{
};
template <typename>
char (&async_result_initiate_memfn_helper(...))[2];
template <typename T>
char async_result_initiate_memfn_helper(
async_result_memfns_check<
void (async_result_memfns_base::*)(),
&async_result_memfns_derived<T>::initiate>*);
template <typename CompletionToken, typename Signature>
struct async_result_has_initiate_memfn
: integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
async_result<typename decay<CompletionToken>::type, Signature>
>(0)) != 1>
{
};
} // namespace detail
#if defined(GENERATING_DOCUMENTATION)
# define ASIO_INITFN_RESULT_TYPE(ct, sig) \
@@ -218,4 +232,125 @@ struct async_result_helper
typename ::asio::decay<ct>::type, sig>::completion_handler_type
#endif
#if defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),
ASIO_MOVE_ARG(Args)... args);
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
inline typename enable_if<
detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
return async_result<typename decay<CompletionToken>::type,
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
ASIO_MOVE_CAST(CompletionToken)(token),
ASIO_MOVE_CAST(Args)(args)...);
}
template <typename CompletionToken, typename Signature,
typename Initiation, typename... Args>
inline typename enable_if<
!detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(Args)... args)
{
async_completion<CompletionToken, Signature> completion(token);
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
Signature))(completion.completion_handler),
ASIO_MOVE_CAST(Args)(args)...);
return completion.result.get();
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename CompletionToken, typename Signature, typename Initiation>
inline typename enable_if<
detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
{
return async_result<typename decay<CompletionToken>::type,
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),
ASIO_MOVE_CAST(CompletionToken)(token));
}
template <typename CompletionToken, typename Signature, typename Initiation>
inline typename enable_if<
!detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type
async_initiate(ASIO_MOVE_ARG(Initiation) initiation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
{
async_completion<CompletionToken, Signature> completion(token);
ASIO_MOVE_CAST(Initiation)(initiation)(
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,
Signature))(completion.completion_handler));
return completion.result.get();
}
#define ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename CompletionToken, typename Signature, \
typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
inline typename enable_if< \
detail::async_result_has_initiate_memfn< \
CompletionToken, Signature>::value, \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_result<typename decay<CompletionToken>::type, \
Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \
ASIO_MOVE_CAST(CompletionToken)(token), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <typename CompletionToken, typename Signature, \
typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \
inline typename enable_if< \
!detail::async_result_has_initiate_memfn< \
CompletionToken, Signature>::value, \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \
async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
async_completion<CompletionToken, Signature> completion(token); \
\
ASIO_MOVE_CAST(Initiation)(initiation)( \
ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \
Signature))(completion.completion_handler), \
ASIO_VARIADIC_MOVE_ARGS(n)); \
\
return completion.result.get(); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
#undef ASIO_PRIVATE_INITIATE_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_ASYNC_RESULT_HPP

View File

@@ -0,0 +1,123 @@
//
// awaitable.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_AWAITABLE_HPP
#define ASIO_AWAITABLE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#include <experimental/coroutine>
#include "asio/executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
using std::experimental::coroutine_handle;
using std::experimental::suspend_always;
template <typename> class awaitable_thread;
template <typename, typename> class awaitable_frame;
} // namespace detail
/// The return type of a coroutine or asynchronous operation.
template <typename T, typename Executor = executor>
class awaitable
{
public:
/// The type of the awaited value.
typedef T value_type;
/// The executor type that will be used for the coroutine.
typedef Executor executor_type;
/// Default constructor.
constexpr awaitable() noexcept
: frame_(nullptr)
{
}
/// Move constructor.
awaitable(awaitable&& other) noexcept
: frame_(std::exchange(other.frame_, nullptr))
{
}
/// Destructor
~awaitable()
{
if (frame_)
frame_->destroy();
}
/// Checks if the awaitable refers to a future result.
bool valid() const noexcept
{
return !!frame_;
}
#if !defined(GENERATING_DOCUMENTATION)
// Support for co_await keyword.
bool await_ready() const noexcept
{
return false;
}
// Support for co_await keyword.
template <class U>
void await_suspend(
detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h)
{
frame_->push_frame(&h.promise());
}
// Support for co_await keyword.
T await_resume()
{
return frame_->get();
}
#endif // !defined(GENERATING_DOCUMENTATION)
private:
template <typename> friend class detail::awaitable_thread;
template <typename, typename> friend class detail::awaitable_frame;
// Not copy constructible or copy assignable.
awaitable(const awaitable&) = delete;
awaitable& operator=(const awaitable&) = delete;
// Construct the awaitable from a coroutine's frame object.
explicit awaitable(detail::awaitable_frame<T, Executor>* a)
: frame_(a)
{
}
detail::awaitable_frame<T, Executor>* frame_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/impl/awaitable.hpp"
#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#endif // ASIO_AWAITABLE_HPP

View File

@@ -2,7 +2,7 @@
// basic_datagram_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -19,18 +19,24 @@
#include <cstddef>
#include "asio/basic_socket.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/datagram_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
#if !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
#define ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol, typename Executor = executor>
class basic_datagram_socket;
#endif // !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
/// Provides datagram-oriented socket functionality.
/**
* The basic_datagram_socket class template provides asynchronous and blocking
@@ -40,18 +46,28 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= datagram_socket_service<Protocol>)>
template <typename Protocol, typename Executor>
class basic_datagram_socket
: public basic_socket<Protocol ASIO_SVC_TARG>
: public basic_socket<Protocol, Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the socket type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The socket type when rebound to the specified executor.
typedef basic_datagram_socket<Protocol, Executor1> other;
};
/// The native representation of a socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_socket<
Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type;
typedef typename basic_socket<Protocol,
Executor>::native_handle_type native_handle_type;
#endif
/// The protocol type.
@@ -65,12 +81,29 @@ public:
* This constructor creates a datagram socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
* @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_datagram_socket(asio::io_context& io_context)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context)
explicit basic_datagram_socket(const executor_type& ex)
: basic_socket<Protocol, Executor>(ex)
{
}
/// Construct a basic_datagram_socket without opening it.
/**
* This constructor creates a datagram socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*/
template <typename ExecutionContext>
explicit basic_datagram_socket(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context)
{
}
@@ -78,17 +111,37 @@ public:
/**
* This constructor creates and opens a datagram socket.
*
* @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_context& io_context,
const protocol_type& protocol)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol)
basic_datagram_socket(const executor_type& ex, const protocol_type& protocol)
: basic_socket<Protocol, Executor>(ex, protocol)
{
}
/// Construct and open a basic_datagram_socket.
/**
* This constructor creates and opens a datagram socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context,
const protocol_type& protocol,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol)
{
}
@@ -99,18 +152,42 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the datagram
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_context& io_context,
const endpoint_type& endpoint)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint)
basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint)
: basic_socket<Protocol, Executor>(ex, endpoint)
{
}
/// Construct a basic_datagram_socket, opening it and binding it to the given
/// local endpoint.
/**
* This constructor creates a datagram socket and automatically opens it bound
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the datagram
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context,
const endpoint_type& endpoint,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, endpoint)
{
}
@@ -119,9 +196,8 @@ public:
* This constructor creates a datagram socket object to hold an existing
* native socket.
*
* @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
@@ -129,10 +205,34 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
basic_datagram_socket(asio::io_context& io_context,
basic_datagram_socket(const executor_type& ex,
const protocol_type& protocol, const native_handle_type& native_socket)
: basic_socket<Protocol ASIO_SVC_TARG>(
io_context, protocol, native_socket)
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
{
}
/// Construct a basic_datagram_socket on an existing native socket.
/**
* This constructor creates a datagram socket object to hold an existing
* native socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
{
}
@@ -145,10 +245,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_datagram_socket(io_context&) constructor.
* constructed using the @c basic_datagram_socket(const executor_type&)
* constructor.
*/
basic_datagram_socket(basic_datagram_socket&& other)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -161,11 +262,12 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_datagram_socket(io_context&) constructor.
* constructed using the @c basic_datagram_socket(const executor_type&)
* constructor.
*/
basic_datagram_socket& operator=(basic_datagram_socket&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
@@ -178,13 +280,16 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_datagram_socket(io_context&) constructor.
* constructed using the @c basic_datagram_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
basic_datagram_socket(
basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
template <typename Protocol1, typename Executor1>
basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -198,14 +303,17 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_datagram_socket(io_context&) constructor.
* constructed using the @c basic_datagram_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_datagram_socket>::type& operator=(
basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other)
template <typename Protocol1, typename Executor1>
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value,
basic_datagram_socket&
>::type operator=(basic_datagram_socket<Protocol1, Executor1>&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -245,8 +353,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -273,8 +381,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -300,8 +408,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().send(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous send on a connected socket.
@@ -322,9 +430,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected datagram
@@ -345,22 +453,10 @@ public:
async_send(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous send on a connected socket.
@@ -383,9 +479,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected datagram
@@ -398,22 +494,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this, buffers, flags);
}
/// Send a datagram to the specified endpoint.
@@ -446,8 +529,8 @@ public:
const endpoint_type& destination)
{
asio::error_code ec;
std::size_t s = this->get_service().send_to(
this->get_implementation(), buffers, destination, 0, ec);
std::size_t s = this->impl_.get_service().send_to(
this->impl_.get_implementation(), buffers, destination, 0, ec);
asio::detail::throw_error(ec, "send_to");
return s;
}
@@ -473,8 +556,8 @@ public:
const endpoint_type& destination, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send_to(
this->get_implementation(), buffers, destination, flags, ec);
std::size_t s = this->impl_.get_service().send_to(
this->impl_.get_implementation(), buffers, destination, flags, ec);
asio::detail::throw_error(ec, "send_to");
return s;
}
@@ -500,7 +583,7 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->get_service().send_to(this->get_implementation(),
return this->impl_.get_service().send_to(this->impl_.get_implementation(),
buffers, destination, flags, ec);
}
@@ -525,9 +608,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -548,24 +631,10 @@ public:
const endpoint_type& destination,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, 0,
ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send_to(
this->get_implementation(), buffers, destination, 0,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send_to(), handler, this, buffers,
destination, socket_base::message_flags(0));
}
/// Start an asynchronous send.
@@ -591,9 +660,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -602,24 +671,9 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send_to(), handler, this, buffers, destination, flags);
}
/// Receive some data on a connected socket.
@@ -650,8 +704,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -679,8 +733,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -707,8 +761,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous receive on a connected socket.
@@ -729,9 +783,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
@@ -753,22 +807,10 @@ public:
async_receive(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous receive on a connected socket.
@@ -791,9 +833,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
@@ -806,22 +848,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this, buffers, flags);
}
/// Receive a datagram with the endpoint of the sender.
@@ -855,8 +884,8 @@ public:
endpoint_type& sender_endpoint)
{
asio::error_code ec;
std::size_t s = this->get_service().receive_from(
this->get_implementation(), buffers, sender_endpoint, 0, ec);
std::size_t s = this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);
asio::detail::throw_error(ec, "receive_from");
return s;
}
@@ -882,8 +911,8 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().receive_from(
this->get_implementation(), buffers, sender_endpoint, flags, ec);
std::size_t s = this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
asio::detail::throw_error(ec, "receive_from");
return s;
}
@@ -909,8 +938,8 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->get_service().receive_from(this->get_implementation(),
buffers, sender_endpoint, flags, ec);
return this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
}
/// Start an asynchronous receive.
@@ -936,9 +965,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -956,24 +985,10 @@ public:
endpoint_type& sender_endpoint,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_from(), handler, this, buffers,
&sender_endpoint, socket_base::message_flags(0));
}
/// Start an asynchronous receive.
@@ -1001,9 +1016,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -1012,25 +1027,85 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_from(), handler,
this, buffers, &sender_endpoint, flags);
}
private:
struct initiate_async_send
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_datagram_socket* self, const ConstBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_send_to
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_datagram_socket* self, const ConstBufferSequence& buffers,
const endpoint_type& destination,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send_to(
self->impl_.get_implementation(), buffers, destination, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_datagram_socket* self, const MutableBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive_from
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_datagram_socket* self, const MutableBufferSequence& buffers,
endpoint_type* sender_endpoint, socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive_from(
self->impl_.get_implementation(), buffers, *sender_endpoint, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
};
} // namespace asio

View File

@@ -2,7 +2,7 @@
// basic_deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -21,19 +21,16 @@
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include "asio/basic_io_object.hpp"
#include "asio/detail/deadline_timer_service.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/io_object_impl.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/execution_context.hpp"
#include "asio/executor.hpp"
#include "asio/time_traits.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/deadline_timer_service.hpp"
#else // defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/detail/deadline_timer_service.hpp"
# define ASIO_SVC_T detail::deadline_timer_service<TimeTraits>
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
@@ -57,7 +54,7 @@ namespace asio {
* Performing a blocking wait:
* @code
* // Construct a timer without setting an expiry time.
* asio::deadline_timer timer(io_context);
* asio::deadline_timer timer(my_context);
*
* // Set an expiry time relative to now.
* timer.expires_from_now(boost::posix_time::seconds(5));
@@ -80,7 +77,7 @@ namespace asio {
* ...
*
* // Construct a timer with an absolute expiry time.
* asio::deadline_timer timer(io_context,
* asio::deadline_timer timer(my_context,
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
*
* // Start an asynchronous wait.
@@ -127,14 +124,13 @@ namespace asio {
* it contains the value asio::error::operation_aborted.
*/
template <typename Time,
typename TimeTraits = asio::time_traits<Time>
ASIO_SVC_TPARAM_DEF2(= deadline_timer_service<Time, TimeTraits>)>
typename TimeTraits = asio::time_traits<Time>,
typename Executor = executor>
class basic_deadline_timer
: ASIO_SVC_ACCESS basic_io_object<ASIO_SVC_T>
{
public:
/// The type of the executor associated with the object.
typedef io_context::executor_type executor_type;
typedef Executor executor_type;
/// The time traits type.
typedef TimeTraits traits_type;
@@ -151,11 +147,30 @@ public:
* expires_at() or expires_from_now() functions must be called to set an
* expiry time before the timer can be waited on.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*/
explicit basic_deadline_timer(asio::io_context& io_context)
: basic_io_object<ASIO_SVC_T>(io_context)
explicit basic_deadline_timer(const executor_type& ex)
: impl_(ex)
{
}
/// Constructor.
/**
* This constructor creates a timer without setting an expiry time. The
* expires_at() or expires_from_now() functions must be called to set an
* expiry time before the timer can be waited on.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*/
template <typename ExecutionContext>
explicit basic_deadline_timer(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
}
@@ -163,18 +178,40 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
basic_deadline_timer(asio::io_context& io_context,
const time_type& expiry_time)
: basic_io_object<ASIO_SVC_T>(io_context)
basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)
: impl_(ex)
{
asio::error_code ec;
this->get_service().expires_at(this->get_implementation(), expiry_time, ec);
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
}
/// Constructor to set a particular expiry time as an absolute time.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
template <typename ExecutionContext>
basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
}
@@ -182,19 +219,44 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
basic_deadline_timer(asio::io_context& io_context,
basic_deadline_timer(const executor_type& ex,
const duration_type& expiry_time)
: basic_io_object<ASIO_SVC_T>(io_context)
: impl_(ex)
{
asio::error_code ec;
this->get_service().expires_from_now(
this->get_implementation(), expiry_time, ec);
impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_from_now");
}
/// Constructor to set a particular expiry time relative to now.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
template <typename ExecutionContext>
basic_deadline_timer(ExecutionContext& context,
const duration_type& expiry_time,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_from_now");
}
@@ -207,10 +269,11 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_deadline_timer(io_context&) constructor.
* constructed using the @c basic_deadline_timer(const executor_type&)
* constructor.
*/
basic_deadline_timer(basic_deadline_timer&& other)
: basic_io_object<ASIO_SVC_T>(std::move(other))
: impl_(std::move(other.impl_))
{
}
@@ -223,11 +286,12 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_deadline_timer(io_context&) constructor.
* constructed using the @c basic_deadline_timer(const executor_type&)
* constructor.
*/
basic_deadline_timer& operator=(basic_deadline_timer&& other)
{
basic_io_object<ASIO_SVC_T>::operator=(std::move(other));
impl_ = std::move(other.impl_);
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -241,45 +305,11 @@ public:
{
}
#if defined(ASIO_ENABLE_OLD_SERVICES)
// These functions are provided by basic_io_object<>.
#else // defined(ASIO_ENABLE_OLD_SERVICES)
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
/**
* This function may be used to obtain the io_context object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_context object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_context& get_io_context()
{
return basic_io_object<ASIO_SVC_T>::get_io_context();
}
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
/**
* This function may be used to obtain the io_context object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_context object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_context& get_io_service()
{
return basic_io_object<ASIO_SVC_T>::get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)
/// Get the executor associated with the object.
executor_type get_executor() ASIO_NOEXCEPT
{
return basic_io_object<ASIO_SVC_T>::get_executor();
return impl_.get_executor();
}
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
/// Cancel any asynchronous operations that are waiting on the timer.
/**
@@ -306,7 +336,7 @@ public:
std::size_t cancel()
{
asio::error_code ec;
std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel");
return s;
}
@@ -335,7 +365,7 @@ public:
*/
std::size_t cancel(asio::error_code& ec)
{
return this->get_service().cancel(this->get_implementation(), ec);
return impl_.get_service().cancel(impl_.get_implementation(), ec);
}
/// Cancels one asynchronous operation that is waiting on the timer.
@@ -365,8 +395,8 @@ public:
std::size_t cancel_one()
{
asio::error_code ec;
std::size_t s = this->get_service().cancel_one(
this->get_implementation(), ec);
std::size_t s = impl_.get_service().cancel_one(
impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel_one");
return s;
}
@@ -397,7 +427,7 @@ public:
*/
std::size_t cancel_one(asio::error_code& ec)
{
return this->get_service().cancel_one(this->get_implementation(), ec);
return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
}
/// Get the timer's expiry time as an absolute time.
@@ -407,7 +437,7 @@ public:
*/
time_type expires_at() const
{
return this->get_service().expires_at(this->get_implementation());
return impl_.get_service().expires_at(impl_.get_implementation());
}
/// Set the timer's expiry time as an absolute time.
@@ -435,8 +465,8 @@ public:
std::size_t expires_at(const time_type& expiry_time)
{
asio::error_code ec;
std::size_t s = this->get_service().expires_at(
this->get_implementation(), expiry_time, ec);
std::size_t s = impl_.get_service().expires_at(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
return s;
}
@@ -466,8 +496,8 @@ public:
std::size_t expires_at(const time_type& expiry_time,
asio::error_code& ec)
{
return this->get_service().expires_at(
this->get_implementation(), expiry_time, ec);
return impl_.get_service().expires_at(
impl_.get_implementation(), expiry_time, ec);
}
/// Get the timer's expiry time relative to now.
@@ -477,7 +507,7 @@ public:
*/
duration_type expires_from_now() const
{
return this->get_service().expires_from_now(this->get_implementation());
return impl_.get_service().expires_from_now(impl_.get_implementation());
}
/// Set the timer's expiry time relative to now.
@@ -505,8 +535,8 @@ public:
std::size_t expires_from_now(const duration_type& expiry_time)
{
asio::error_code ec;
std::size_t s = this->get_service().expires_from_now(
this->get_implementation(), expiry_time, ec);
std::size_t s = impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_from_now");
return s;
}
@@ -536,8 +566,8 @@ public:
std::size_t expires_from_now(const duration_type& expiry_time,
asio::error_code& ec)
{
return this->get_service().expires_from_now(
this->get_implementation(), expiry_time, ec);
return impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
}
/// Perform a blocking wait on the timer.
@@ -550,7 +580,7 @@ public:
void wait()
{
asio::error_code ec;
this->get_service().wait(this->get_implementation(), ec);
impl_.get_service().wait(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "wait");
}
@@ -563,7 +593,7 @@ public:
*/
void wait(asio::error_code& ec)
{
this->get_service().wait(this->get_implementation(), ec);
impl_.get_service().wait(impl_.get_implementation(), ec);
}
/// Start an asynchronous wait on the timer.
@@ -586,42 +616,50 @@ public:
* const asio::error_code& error // Result of operation.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename WaitHandler>
ASIO_INITFN_RESULT_TYPE(WaitHandler,
void (asio::error_code))
async_wait(ASIO_MOVE_ARG(WaitHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WaitHandler.
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_wait(this->get_implementation(),
ASIO_MOVE_CAST(WaitHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WaitHandler,
void (asio::error_code)> init(handler);
this->get_service().async_wait(this->get_implementation(),
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WaitHandler, void (asio::error_code)>(
initiate_async_wait(), handler, this);
}
private:
// Disallow copying and assignment.
basic_deadline_timer(const basic_deadline_timer&) ASIO_DELETED;
basic_deadline_timer& operator=(
const basic_deadline_timer&) ASIO_DELETED;
struct initiate_async_wait
{
template <typename WaitHandler>
void operator()(ASIO_MOVE_ARG(WaitHandler) handler,
basic_deadline_timer* self) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WaitHandler.
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
detail::non_const_lvalue<WaitHandler> handler2(handler);
self->impl_.get_service().async_wait(
self->impl_.get_implementation(), handler2.value,
self->impl_.get_implementation_executor());
}
};
detail::io_object_impl<
detail::deadline_timer_service<TimeTraits>, Executor> impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#if !defined(ASIO_ENABLE_OLD_SERVICES)
# undef ASIO_SVC_T
#endif // !defined(ASIO_ENABLE_OLD_SERVICES)
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// || defined(GENERATING_DOCUMENTATION)

View File

@@ -2,7 +2,7 @@
// basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// basic_raw_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -19,18 +19,24 @@
#include <cstddef>
#include "asio/basic_socket.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/raw_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
#if !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)
#define ASIO_BASIC_RAW_SOCKET_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol, typename Executor = executor>
class basic_raw_socket;
#endif // !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)
/// Provides raw-oriented socket functionality.
/**
* The basic_raw_socket class template provides asynchronous and blocking
@@ -40,18 +46,28 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= raw_socket_service<Protocol>)>
template <typename Protocol, typename Executor>
class basic_raw_socket
: public basic_socket<Protocol ASIO_SVC_TARG>
: public basic_socket<Protocol, Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the socket type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The socket type when rebound to the specified executor.
typedef basic_raw_socket<Protocol, Executor1> other;
};
/// The native representation of a socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_socket<
Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type;
typedef typename basic_socket<Protocol,
Executor>::native_handle_type native_handle_type;
#endif
/// The protocol type.
@@ -65,12 +81,29 @@ public:
* This constructor creates a raw socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
* @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_raw_socket(asio::io_context& io_context)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context)
explicit basic_raw_socket(const executor_type& ex)
: basic_socket<Protocol, Executor>(ex)
{
}
/// Construct a basic_raw_socket without opening it.
/**
* This constructor creates a raw socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*/
template <typename ExecutionContext>
explicit basic_raw_socket(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context)
{
}
@@ -78,17 +111,36 @@ public:
/**
* This constructor creates and opens a raw socket.
*
* @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_raw_socket(asio::io_context& io_context,
const protocol_type& protocol)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol)
basic_raw_socket(const executor_type& ex, const protocol_type& protocol)
: basic_socket<Protocol, Executor>(ex, protocol)
{
}
/// Construct and open a basic_raw_socket.
/**
* This constructor creates and opens a raw socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol)
{
}
@@ -99,18 +151,41 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the raw
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_raw_socket(asio::io_context& io_context,
const endpoint_type& endpoint)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint)
basic_raw_socket(const executor_type& ex, const endpoint_type& endpoint)
: basic_socket<Protocol, Executor>(ex, endpoint)
{
}
/// Construct a basic_raw_socket, opening it and binding it to the given
/// local endpoint.
/**
* This constructor creates a raw socket and automatically opens it bound
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the raw
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, endpoint)
{
}
@@ -119,9 +194,8 @@ public:
* This constructor creates a raw socket object to hold an existing
* native socket.
*
* @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
@@ -129,10 +203,34 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
basic_raw_socket(asio::io_context& io_context,
basic_raw_socket(const executor_type& ex,
const protocol_type& protocol, const native_handle_type& native_socket)
: basic_socket<Protocol ASIO_SVC_TARG>(
io_context, protocol, native_socket)
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
{
}
/// Construct a basic_raw_socket on an existing native socket.
/**
* This constructor creates a raw socket object to hold an existing
* native socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
{
}
@@ -145,10 +243,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_raw_socket(io_context&) constructor.
* constructed using the @c basic_raw_socket(const executor_type&)
* constructor.
*/
basic_raw_socket(basic_raw_socket&& other)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -160,28 +259,34 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_raw_socket(io_context&) constructor.
* constructed using the @c basic_raw_socket(const executor_type&)
* constructor.
*/
basic_raw_socket& operator=(basic_raw_socket&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
/// Move-construct a basic_raw_socket from a socket of another protocol type.
/// Move-construct a basic_raw_socket from a socket of another protocol
/// type.
/**
* This constructor moves a raw socket from one object to another.
*
* @param other The other basic_raw_socket object from which the move will
* occur.
* @param other The other basic_raw_socket object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_raw_socket(io_context&) constructor.
* constructed using the @c basic_raw_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
basic_raw_socket(basic_raw_socket<Protocol1 ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
template <typename Protocol1, typename Executor1>
basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -193,14 +298,17 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_raw_socket(io_context&) constructor.
* constructed using the @c basic_raw_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_raw_socket>::type& operator=(
basic_raw_socket<Protocol1 ASIO_SVC_TARG1>&& other)
template <typename Protocol1, typename Executor1>
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value,
basic_raw_socket&
>::type operator=(basic_raw_socket<Protocol1, Executor1>&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -239,8 +347,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -266,8 +374,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -292,8 +400,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().send(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous send on a connected socket.
@@ -314,9 +422,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected raw
@@ -337,22 +445,10 @@ public:
async_send(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous send on a connected socket.
@@ -375,9 +471,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_send operation can only be used with a connected socket.
* Use the async_send_to function to send data on an unconnected raw
@@ -390,22 +486,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this, buffers, flags);
}
/// Send raw data to the specified endpoint.
@@ -438,8 +521,8 @@ public:
const endpoint_type& destination)
{
asio::error_code ec;
std::size_t s = this->get_service().send_to(
this->get_implementation(), buffers, destination, 0, ec);
std::size_t s = this->impl_.get_service().send_to(
this->impl_.get_implementation(), buffers, destination, 0, ec);
asio::detail::throw_error(ec, "send_to");
return s;
}
@@ -465,8 +548,8 @@ public:
const endpoint_type& destination, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send_to(
this->get_implementation(), buffers, destination, flags, ec);
std::size_t s = this->impl_.get_service().send_to(
this->impl_.get_implementation(), buffers, destination, flags, ec);
asio::detail::throw_error(ec, "send_to");
return s;
}
@@ -492,7 +575,7 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->get_service().send_to(this->get_implementation(),
return this->impl_.get_service().send_to(this->impl_.get_implementation(),
buffers, destination, flags, ec);
}
@@ -517,9 +600,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -540,22 +623,10 @@ public:
const endpoint_type& destination,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(this->get_implementation(),
buffers, destination, 0, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send_to(this->get_implementation(),
buffers, destination, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send_to(), handler, this, buffers,
destination, socket_base::message_flags(0));
}
/// Start an asynchronous send.
@@ -581,9 +652,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -592,24 +663,9 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send_to(), handler, this, buffers, destination, flags);
}
/// Receive some data on a connected socket.
@@ -640,8 +696,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -669,8 +725,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -697,8 +753,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous receive on a connected socket.
@@ -719,9 +775,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
@@ -743,22 +799,10 @@ public:
async_receive(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous receive on a connected socket.
@@ -781,9 +825,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The async_receive operation can only be used with a connected socket.
* Use the async_receive_from function to receive data on an unconnected
@@ -796,22 +840,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this, buffers, flags);
}
/// Receive raw data with the endpoint of the sender.
@@ -845,8 +876,8 @@ public:
endpoint_type& sender_endpoint)
{
asio::error_code ec;
std::size_t s = this->get_service().receive_from(
this->get_implementation(), buffers, sender_endpoint, 0, ec);
std::size_t s = this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);
asio::detail::throw_error(ec, "receive_from");
return s;
}
@@ -872,8 +903,8 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().receive_from(
this->get_implementation(), buffers, sender_endpoint, flags, ec);
std::size_t s = this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
asio::detail::throw_error(ec, "receive_from");
return s;
}
@@ -899,8 +930,8 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
asio::error_code& ec)
{
return this->get_service().receive_from(this->get_implementation(),
buffers, sender_endpoint, flags, ec);
return this->impl_.get_service().receive_from(
this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
}
/// Start an asynchronous receive.
@@ -926,9 +957,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -946,24 +977,10 @@ public:
endpoint_type& sender_endpoint,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_from(), handler, this, buffers,
&sender_endpoint, socket_base::message_flags(0));
}
/// Start an asynchronous receive.
@@ -991,9 +1008,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -1002,25 +1019,85 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_from(), handler,
this, buffers, &sender_endpoint, flags);
}
private:
struct initiate_async_send
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_raw_socket* self, const ConstBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_send_to
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_raw_socket* self, const ConstBufferSequence& buffers,
const endpoint_type& destination,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send_to(
self->impl_.get_implementation(), buffers, destination, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_raw_socket* self, const MutableBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive_from
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_raw_socket* self, const MutableBufferSequence& buffers,
endpoint_type* sender_endpoint, socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive_from(
self->impl_.get_implementation(), buffers, *sender_endpoint, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
};
} // namespace asio

View File

@@ -2,7 +2,7 @@
// basic_seq_packet_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -22,14 +22,19 @@
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/seq_packet_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
#if !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
#define ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol, typename Executor = executor>
class basic_seq_packet_socket;
#endif // !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
/// Provides sequenced packet socket functionality.
/**
* The basic_seq_packet_socket class template provides asynchronous and blocking
@@ -39,18 +44,28 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= seq_packet_socket_service<Protocol>)>
template <typename Protocol, typename Executor>
class basic_seq_packet_socket
: public basic_socket<Protocol ASIO_SVC_TARG>
: public basic_socket<Protocol, Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the socket type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The socket type when rebound to the specified executor.
typedef basic_seq_packet_socket<Protocol, Executor1> other;
};
/// The native representation of a socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_socket<
Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type;
typedef typename basic_socket<Protocol,
Executor>::native_handle_type native_handle_type;
#endif
/// The protocol type.
@@ -65,12 +80,30 @@ public:
* socket needs to be opened and then connected or accepted before data can
* be sent or received on it.
*
* @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_seq_packet_socket(asio::io_context& io_context)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context)
explicit basic_seq_packet_socket(const executor_type& ex)
: basic_socket<Protocol, Executor>(ex)
{
}
/// Construct a basic_seq_packet_socket without opening it.
/**
* This constructor creates a sequenced packet socket without opening it. The
* socket needs to be opened and then connected or accepted before data can
* be sent or received on it.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*/
template <typename ExecutionContext>
explicit basic_seq_packet_socket(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context)
{
}
@@ -80,17 +113,40 @@ public:
* needs to be connected or accepted before data can be sent or received on
* it.
*
* @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_context& io_context,
basic_seq_packet_socket(const executor_type& ex,
const protocol_type& protocol)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol)
: basic_socket<Protocol, Executor>(ex, protocol)
{
}
/// Construct and open a basic_seq_packet_socket.
/**
* This constructor creates and opens a sequenced_packet socket. The socket
* needs to be connected or accepted before data can be sent or received on
* it.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context,
const protocol_type& protocol,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol)
{
}
@@ -101,18 +157,43 @@ public:
* it bound to the specified endpoint on the local machine. The protocol used
* is the protocol associated with the given endpoint.
*
* @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the sequenced
* packet socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_context& io_context,
basic_seq_packet_socket(const executor_type& ex,
const endpoint_type& endpoint)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint)
: basic_socket<Protocol, Executor>(ex, endpoint)
{
}
/// Construct a basic_seq_packet_socket, opening it and binding it to the
/// given local endpoint.
/**
* This constructor creates a sequenced packet socket and automatically opens
* it bound to the specified endpoint on the local machine. The protocol used
* is the protocol associated with the given endpoint.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the sequenced
* packet socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context,
const endpoint_type& endpoint,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, endpoint)
{
}
@@ -121,9 +202,8 @@ public:
* This constructor creates a sequenced packet socket object to hold an
* existing native socket.
*
* @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
@@ -131,10 +211,34 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_context& io_context,
basic_seq_packet_socket(const executor_type& ex,
const protocol_type& protocol, const native_handle_type& native_socket)
: basic_socket<Protocol ASIO_SVC_TARG>(
io_context, protocol, native_socket)
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
{
}
/// Construct a basic_seq_packet_socket on an existing native socket.
/**
* This constructor creates a sequenced packet socket object to hold an
* existing native socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
{
}
@@ -148,10 +252,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
* constructed using the @c basic_seq_packet_socket(const executor_type&)
* constructor.
*/
basic_seq_packet_socket(basic_seq_packet_socket&& other)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -164,11 +269,12 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
* constructed using the @c basic_seq_packet_socket(const executor_type&)
* constructor.
*/
basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
@@ -182,13 +288,16 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
* constructed using the @c basic_seq_packet_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
basic_seq_packet_socket(
basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
template <typename Protocol1, typename Executor1>
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -202,14 +311,17 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
* constructed using the @c basic_seq_packet_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_seq_packet_socket>::type& operator=(
basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1>&& other)
template <typename Protocol1, typename Executor1>
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value,
basic_seq_packet_socket&
>::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -251,8 +363,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -279,8 +391,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().send(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous send.
@@ -303,9 +415,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -323,22 +435,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this, buffers, flags);
}
/// Receive some data on the socket.
@@ -375,13 +474,8 @@ public:
socket_base::message_flags& out_flags)
{
asio::error_code ec;
#if defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, out_flags, ec);
#else // defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive_with_flags(
this->get_implementation(), buffers, 0, out_flags, ec);
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->impl_.get_service().receive_with_flags(
this->impl_.get_implementation(), buffers, 0, out_flags, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -427,13 +521,8 @@ public:
socket_base::message_flags& out_flags)
{
asio::error_code ec;
#if defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, in_flags, out_flags, ec);
#else // defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive_with_flags(
this->get_implementation(), buffers, in_flags, out_flags, ec);
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->impl_.get_service().receive_with_flags(
this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -466,13 +555,8 @@ public:
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().receive(this->get_implementation(),
buffers, in_flags, out_flags, ec);
#else // defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().receive_with_flags(this->get_implementation(),
buffers, in_flags, out_flags, ec);
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return this->impl_.get_service().receive_with_flags(
this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
}
/// Start an asynchronous receive.
@@ -499,9 +583,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -520,24 +604,10 @@ public:
socket_base::message_flags& out_flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(
this->get_implementation(), buffers, 0, out_flags,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_with_flags(
this->get_implementation(), buffers, 0, out_flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_with_flags(), handler, this,
buffers, socket_base::message_flags(0), &out_flags);
}
/// Start an asynchronous receive.
@@ -566,9 +636,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -590,25 +660,49 @@ public:
socket_base::message_flags& out_flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(
this->get_implementation(), buffers, in_flags, out_flags,
ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive_with_flags(
this->get_implementation(), buffers, in_flags, out_flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive_with_flags(), handler,
this, buffers, in_flags, &out_flags);
}
private:
struct initiate_async_send
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_seq_packet_socket* self, const ConstBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive_with_flags
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_seq_packet_socket* self, const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags* out_flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive_with_flags(
self->impl_.get_implementation(), buffers, in_flags, *out_flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
};
} // namespace asio

View File

@@ -2,7 +2,7 @@
// basic_serial_port.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -18,18 +18,29 @@
#include "asio/detail/config.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
#if defined(ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
#include <string>
#include "asio/basic_io_object.hpp"
#include "asio/async_result.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/io_object_impl.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/execution_context.hpp"
#include "asio/executor.hpp"
#include "asio/serial_port_base.hpp"
#include "asio/serial_port_service.hpp"
#if defined(ASIO_HAS_IOCP)
# include "asio/detail/win_iocp_serial_port_service.hpp"
#else
# include "asio/detail/reactive_serial_port_service.hpp"
#endif
#if defined(ASIO_HAS_MOVE)
# include <utility>
#endif // defined(ASIO_HAS_MOVE)
#include "asio/detail/push_options.hpp"
@@ -37,34 +48,63 @@ namespace asio {
/// Provides serial port functionality.
/**
* The basic_serial_port class template provides functionality that is common
* to all serial ports.
* The basic_serial_port class provides a wrapper over serial port
* functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename SerialPortService = serial_port_service>
template <typename Executor = executor>
class basic_serial_port
: public basic_io_object<SerialPortService>,
public serial_port_base
: public serial_port_base
{
public:
/// The native representation of a serial port.
typedef typename SerialPortService::native_handle_type native_handle_type;
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// A basic_serial_port is always the lowest layer.
typedef basic_serial_port<SerialPortService> lowest_layer_type;
/// The native representation of a serial port.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#elif defined(ASIO_HAS_IOCP)
typedef detail::win_iocp_serial_port_service::native_handle_type
native_handle_type;
#else
typedef detail::reactive_serial_port_service::native_handle_type
native_handle_type;
#endif
/// A basic_basic_serial_port is always the lowest layer.
typedef basic_serial_port lowest_layer_type;
/// Construct a basic_serial_port without opening it.
/**
* This constructor creates a serial port without opening it.
*
* @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
* @param ex The I/O executor that the serial port will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* serial port.
*/
explicit basic_serial_port(asio::io_context& io_context)
: basic_io_object<SerialPortService>(io_context)
explicit basic_serial_port(const executor_type& ex)
: impl_(ex)
{
}
/// Construct a basic_serial_port without opening it.
/**
* This constructor creates a serial port without opening it.
*
* @param context An execution context which provides the I/O executor that
* the serial port will use, by default, to dispatch handlers for any
* asynchronous operations performed on the serial port.
*/
template <typename ExecutionContext>
explicit basic_serial_port(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value,
basic_serial_port
>::type* = 0)
: impl_(context)
{
}
@@ -73,18 +113,18 @@ public:
* This constructor creates and opens a serial port for the specified device
* name.
*
* @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
* @param ex The I/O executor that the serial port will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* serial port.
*
* @param device The platform-specific device name for this serial
* port.
*/
explicit basic_serial_port(asio::io_context& io_context,
const char* device)
: basic_io_object<SerialPortService>(io_context)
basic_serial_port(const executor_type& ex, const char* device)
: impl_(ex)
{
asio::error_code ec;
this->get_service().open(this->get_implementation(), device, ec);
impl_.get_service().open(impl_.get_implementation(), device, ec);
asio::detail::throw_error(ec, "open");
}
@@ -93,18 +133,66 @@ public:
* This constructor creates and opens a serial port for the specified device
* name.
*
* @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
* @param context An execution context which provides the I/O executor that
* the serial port will use, by default, to dispatch handlers for any
* asynchronous operations performed on the serial port.
*
* @param device The platform-specific device name for this serial
* port.
*/
explicit basic_serial_port(asio::io_context& io_context,
const std::string& device)
: basic_io_object<SerialPortService>(io_context)
template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context, const char* device,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
this->get_service().open(this->get_implementation(), device, ec);
impl_.get_service().open(impl_.get_implementation(), device, ec);
asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_serial_port.
/**
* This constructor creates and opens a serial port for the specified device
* name.
*
* @param ex The I/O executor that the serial port will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* serial port.
*
* @param device The platform-specific device name for this serial
* port.
*/
basic_serial_port(const executor_type& ex, const std::string& device)
: impl_(ex)
{
asio::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec);
asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_serial_port.
/**
* This constructor creates and opens a serial port for the specified device
* name.
*
* @param context An execution context which provides the I/O executor that
* the serial port will use, by default, to dispatch handlers for any
* asynchronous operations performed on the serial port.
*
* @param device The platform-specific device name for this serial
* port.
*/
template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context, const std::string& device,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec);
asio::detail::throw_error(ec, "open");
}
@@ -113,19 +201,47 @@ public:
* This constructor creates a serial port object to hold an existing native
* serial port.
*
* @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
* @param ex The I/O executor that the serial port will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* serial port.
*
* @param native_serial_port A native serial port.
*
* @throws asio::system_error Thrown on failure.
*/
basic_serial_port(asio::io_context& io_context,
basic_serial_port(const executor_type& ex,
const native_handle_type& native_serial_port)
: basic_io_object<SerialPortService>(io_context)
: impl_(ex)
{
asio::error_code ec;
this->get_service().assign(this->get_implementation(),
impl_.get_service().assign(impl_.get_implementation(),
native_serial_port, ec);
asio::detail::throw_error(ec, "assign");
}
/// Construct a basic_serial_port on an existing native serial port.
/**
* This constructor creates a serial port object to hold an existing native
* serial port.
*
* @param context An execution context which provides the I/O executor that
* the serial port will use, by default, to dispatch handlers for any
* asynchronous operations performed on the serial port.
*
* @param native_serial_port A native serial port.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context,
const native_handle_type& native_serial_port,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().assign(impl_.get_implementation(),
native_serial_port, ec);
asio::detail::throw_error(ec, "assign");
}
@@ -139,11 +255,11 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_serial_port(io_context&) constructor.
* constructed using the @c basic_serial_port(const executor_type&)
* constructor.
*/
basic_serial_port(basic_serial_port&& other)
: basic_io_object<SerialPortService>(
ASIO_MOVE_CAST(basic_serial_port)(other))
: impl_(std::move(other.impl_))
{
}
@@ -155,16 +271,32 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_serial_port(io_context&) constructor.
* constructed using the @c basic_serial_port(const executor_type&)
* constructor.
*/
basic_serial_port& operator=(basic_serial_port&& other)
{
basic_io_object<SerialPortService>::operator=(
ASIO_MOVE_CAST(basic_serial_port)(other));
impl_ = std::move(other.impl_);
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroys the serial port.
/**
* This function destroys the serial port, cancelling any outstanding
* asynchronous wait operations associated with the serial port as if by
* calling @c cancel.
*/
~basic_serial_port()
{
}
/// Get the executor associated with the object.
executor_type get_executor() ASIO_NOEXCEPT
{
return impl_.get_executor();
}
/// Get a reference to the lowest layer.
/**
* This function returns a reference to the lowest layer in a stack of
@@ -204,7 +336,7 @@ public:
void open(const std::string& device)
{
asio::error_code ec;
this->get_service().open(this->get_implementation(), device, ec);
impl_.get_service().open(impl_.get_implementation(), device, ec);
asio::detail::throw_error(ec, "open");
}
@@ -220,7 +352,7 @@ public:
ASIO_SYNC_OP_VOID open(const std::string& device,
asio::error_code& ec)
{
this->get_service().open(this->get_implementation(), device, ec);
impl_.get_service().open(impl_.get_implementation(), device, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -235,7 +367,7 @@ public:
void assign(const native_handle_type& native_serial_port)
{
asio::error_code ec;
this->get_service().assign(this->get_implementation(),
impl_.get_service().assign(impl_.get_implementation(),
native_serial_port, ec);
asio::detail::throw_error(ec, "assign");
}
@@ -251,7 +383,7 @@ public:
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
asio::error_code& ec)
{
this->get_service().assign(this->get_implementation(),
impl_.get_service().assign(impl_.get_implementation(),
native_serial_port, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -259,7 +391,7 @@ public:
/// Determine whether the serial port is open.
bool is_open() const
{
return this->get_service().is_open(this->get_implementation());
return impl_.get_service().is_open(impl_.get_implementation());
}
/// Close the serial port.
@@ -273,7 +405,7 @@ public:
void close()
{
asio::error_code ec;
this->get_service().close(this->get_implementation(), ec);
impl_.get_service().close(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "close");
}
@@ -287,7 +419,7 @@ public:
*/
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
{
this->get_service().close(this->get_implementation(), ec);
impl_.get_service().close(impl_.get_implementation(), ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -299,7 +431,7 @@ public:
*/
native_handle_type native_handle()
{
return this->get_service().native_handle(this->get_implementation());
return impl_.get_service().native_handle(impl_.get_implementation());
}
/// Cancel all asynchronous operations associated with the serial port.
@@ -313,7 +445,7 @@ public:
void cancel()
{
asio::error_code ec;
this->get_service().cancel(this->get_implementation(), ec);
impl_.get_service().cancel(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel");
}
@@ -327,7 +459,7 @@ public:
*/
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
{
this->get_service().cancel(this->get_implementation(), ec);
impl_.get_service().cancel(impl_.get_implementation(), ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -341,7 +473,7 @@ public:
void send_break()
{
asio::error_code ec;
this->get_service().send_break(this->get_implementation(), ec);
impl_.get_service().send_break(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "send_break");
}
@@ -354,7 +486,7 @@ public:
*/
ASIO_SYNC_OP_VOID send_break(asio::error_code& ec)
{
this->get_service().send_break(this->get_implementation(), ec);
impl_.get_service().send_break(impl_.get_implementation(), ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -377,7 +509,7 @@ public:
void set_option(const SettableSerialPortOption& option)
{
asio::error_code ec;
this->get_service().set_option(this->get_implementation(), option, ec);
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
asio::detail::throw_error(ec, "set_option");
}
@@ -400,7 +532,7 @@ public:
ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
asio::error_code& ec)
{
this->get_service().set_option(this->get_implementation(), option, ec);
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -424,7 +556,7 @@ public:
void get_option(GettableSerialPortOption& option)
{
asio::error_code ec;
this->get_service().get_option(this->get_implementation(), option, ec);
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
asio::detail::throw_error(ec, "get_option");
}
@@ -448,7 +580,7 @@ public:
ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
asio::error_code& ec)
{
this->get_service().get_option(this->get_implementation(), option, ec);
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -473,7 +605,7 @@ public:
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* serial_port.write_some(asio::buffer(data, size));
* basic_serial_port.write_some(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
@@ -483,8 +615,8 @@ public:
std::size_t write_some(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().write_some(
this->get_implementation(), buffers, ec);
std::size_t s = impl_.get_service().write_some(
impl_.get_implementation(), buffers, ec);
asio::detail::throw_error(ec, "write_some");
return s;
}
@@ -509,8 +641,8 @@ public:
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return this->get_service().write_some(
this->get_implementation(), buffers, ec);
return impl_.get_service().write_some(
impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous write.
@@ -531,9 +663,9 @@ public:
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The write operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
@@ -542,7 +674,8 @@ public:
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* serial_port.async_write_some(asio::buffer(data, size), handler);
* basic_serial_port.async_write_some(
* asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
@@ -554,12 +687,9 @@ public:
async_write_some(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
return this->get_service().async_write_some(this->get_implementation(),
buffers, ASIO_MOVE_CAST(WriteHandler)(handler));
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_write_some(), handler, this, buffers);
}
/// Read some data from the serial port.
@@ -584,7 +714,7 @@ public:
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* serial_port.read_some(asio::buffer(data, size));
* basic_serial_port.read_some(asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
@@ -594,8 +724,8 @@ public:
std::size_t read_some(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().read_some(
this->get_implementation(), buffers, ec);
std::size_t s = impl_.get_service().read_some(
impl_.get_implementation(), buffers, ec);
asio::detail::throw_error(ec, "read_some");
return s;
}
@@ -621,8 +751,8 @@ public:
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return this->get_service().read_some(
this->get_implementation(), buffers, ec);
return impl_.get_service().read_some(
impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous read.
@@ -643,9 +773,9 @@ public:
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read function if you need to ensure that the
@@ -655,7 +785,8 @@ public:
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* serial_port.async_read_some(asio::buffer(data, size), handler);
* basic_serial_port.async_read_some(
* asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
@@ -667,13 +798,55 @@ public:
async_read_some(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
return this->get_service().async_read_some(this->get_implementation(),
buffers, ASIO_MOVE_CAST(ReadHandler)(handler));
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_read_some(), handler, this, buffers);
}
private:
// Disallow copying and assignment.
basic_serial_port(const basic_serial_port&) ASIO_DELETED;
basic_serial_port& operator=(const basic_serial_port&) ASIO_DELETED;
struct initiate_async_write_some
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_serial_port* self, const ConstBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_write_some(
self->impl_.get_implementation(), buffers, handler2.value,
self->impl_.get_implementation_executor());
}
};
struct initiate_async_read_some
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_serial_port* self, const MutableBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_read_some(
self->impl_.get_implementation(), buffers, handler2.value,
self->impl_.get_implementation_executor());
}
};
#if defined(ASIO_HAS_IOCP)
detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_;
#else
detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_;
#endif
};
} // namespace asio
@@ -683,6 +856,4 @@ public:
#endif // defined(ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#endif // ASIO_BASIC_SERIAL_PORT_HPP

View File

@@ -2,7 +2,7 @@
// basic_signal_set.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,24 +17,23 @@
#include "asio/detail/config.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/basic_io_object.hpp"
#include "asio/async_result.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/io_object_impl.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/signal_set_service.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/signal_set_service.hpp"
#include "asio/detail/push_options.hpp"
#include "asio/execution_context.hpp"
#include "asio/executor.hpp"
namespace asio {
/// Provides signal functionality.
/**
* The basic_signal_set class template provides the ability to perform an
* asynchronous wait for one or more signals to occur.
*
* Most applications will use the asio::signal_set typedef.
* The basic_signal_set class provides the ability to perform an asynchronous
* wait for one or more signals to occur.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
@@ -56,7 +55,7 @@ namespace asio {
* ...
*
* // Construct a signal set registered for process termination.
* asio::signal_set signals(io_context, SIGINT, SIGTERM);
* asio::signal_set signals(my_context, SIGINT, SIGTERM);
*
* // Start an asynchronous wait for one of the signals to occur.
* signals.async_wait(handler);
@@ -91,20 +90,40 @@ namespace asio {
* that any signals registered using signal_set objects are unblocked in at
* least one thread.
*/
template <typename SignalSetService = signal_set_service>
template <typename Executor = executor>
class basic_signal_set
: public basic_io_object<SignalSetService>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Construct a signal set without adding any signals.
/**
* This constructor creates a signal set without registering for any signals.
*
* @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
* @param ex The I/O executor that the signal set will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* signal set.
*/
explicit basic_signal_set(asio::io_context& io_context)
: basic_io_object<SignalSetService>(io_context)
explicit basic_signal_set(const executor_type& ex)
: impl_(ex)
{
}
/// Construct a signal set without adding any signals.
/**
* This constructor creates a signal set without registering for any signals.
*
* @param context An execution context which provides the I/O executor that
* the signal set will use, by default, to dispatch handlers for any
* asynchronous operations performed on the signal set.
*/
template <typename ExecutionContext>
explicit basic_signal_set(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
}
@@ -112,20 +131,47 @@ public:
/**
* This constructor creates a signal set and registers for one signal.
*
* @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
* @param ex The I/O executor that the signal set will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* signal set.
*
* @param signal_number_1 The signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(io_context);
* @code asio::signal_set signals(ex);
* signals.add(signal_number_1); @endcode
*/
basic_signal_set(asio::io_context& io_context, int signal_number_1)
: basic_io_object<SignalSetService>(io_context)
basic_signal_set(const executor_type& ex, int signal_number_1)
: impl_(ex)
{
asio::error_code ec;
this->get_service().add(this->get_implementation(), signal_number_1, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
}
/// Construct a signal set and add one signal.
/**
* This constructor creates a signal set and registers for one signal.
*
* @param context An execution context which provides the I/O executor that
* the signal set will use, by default, to dispatch handlers for any
* asynchronous operations performed on the signal set.
*
* @param signal_number_1 The signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(context);
* signals.add(signal_number_1); @endcode
*/
template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
}
@@ -133,26 +179,59 @@ public:
/**
* This constructor creates a signal set and registers for two signals.
*
* @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
* @param ex The I/O executor that the signal set will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* signal set.
*
* @param signal_number_1 The first signal number to be added.
*
* @param signal_number_2 The second signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(io_context);
* @code asio::signal_set signals(ex);
* signals.add(signal_number_1);
* signals.add(signal_number_2); @endcode
*/
basic_signal_set(asio::io_context& io_context, int signal_number_1,
basic_signal_set(const executor_type& ex, int signal_number_1,
int signal_number_2)
: basic_io_object<SignalSetService>(io_context)
: impl_(ex)
{
asio::error_code ec;
this->get_service().add(this->get_implementation(), signal_number_1, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
this->get_service().add(this->get_implementation(), signal_number_2, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
asio::detail::throw_error(ec, "add");
}
/// Construct a signal set and add two signals.
/**
* This constructor creates a signal set and registers for two signals.
*
* @param context An execution context which provides the I/O executor that
* the signal set will use, by default, to dispatch handlers for any
* asynchronous operations performed on the signal set.
*
* @param signal_number_1 The first signal number to be added.
*
* @param signal_number_2 The second signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(context);
* signals.add(signal_number_1);
* signals.add(signal_number_2); @endcode
*/
template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1,
int signal_number_2,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
asio::detail::throw_error(ec, "add");
}
@@ -160,8 +239,9 @@ public:
/**
* This constructor creates a signal set and registers for three signals.
*
* @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
* @param ex The I/O executor that the signal set will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* signal set.
*
* @param signal_number_1 The first signal number to be added.
*
@@ -170,24 +250,77 @@ public:
* @param signal_number_3 The third signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(io_context);
* @code asio::signal_set signals(ex);
* signals.add(signal_number_1);
* signals.add(signal_number_2);
* signals.add(signal_number_3); @endcode
*/
basic_signal_set(asio::io_context& io_context, int signal_number_1,
basic_signal_set(const executor_type& ex, int signal_number_1,
int signal_number_2, int signal_number_3)
: basic_io_object<SignalSetService>(io_context)
: impl_(ex)
{
asio::error_code ec;
this->get_service().add(this->get_implementation(), signal_number_1, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
this->get_service().add(this->get_implementation(), signal_number_2, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
asio::detail::throw_error(ec, "add");
this->get_service().add(this->get_implementation(), signal_number_3, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
asio::detail::throw_error(ec, "add");
}
/// Construct a signal set and add three signals.
/**
* This constructor creates a signal set and registers for three signals.
*
* @param context An execution context which provides the I/O executor that
* the signal set will use, by default, to dispatch handlers for any
* asynchronous operations performed on the signal set.
*
* @param signal_number_1 The first signal number to be added.
*
* @param signal_number_2 The second signal number to be added.
*
* @param signal_number_3 The third signal number to be added.
*
* @note This constructor is equivalent to performing:
* @code asio::signal_set signals(context);
* signals.add(signal_number_1);
* signals.add(signal_number_2);
* signals.add(signal_number_3); @endcode
*/
template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1,
int signal_number_2, int signal_number_3,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
asio::detail::throw_error(ec, "add");
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
asio::detail::throw_error(ec, "add");
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
asio::detail::throw_error(ec, "add");
}
/// Destroys the signal set.
/**
* This function destroys the signal set, cancelling any outstanding
* asynchronous wait operations associated with the signal set as if by
* calling @c cancel.
*/
~basic_signal_set()
{
}
/// Get the executor associated with the object.
executor_type get_executor() ASIO_NOEXCEPT
{
return impl_.get_executor();
}
/// Add a signal to a signal_set.
/**
* This function adds the specified signal to the set. It has no effect if the
@@ -200,7 +333,7 @@ public:
void add(int signal_number)
{
asio::error_code ec;
this->get_service().add(this->get_implementation(), signal_number, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
asio::detail::throw_error(ec, "add");
}
@@ -213,9 +346,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
ASIO_SYNC_OP_VOID add(int signal_number, asio::error_code& ec)
ASIO_SYNC_OP_VOID add(int signal_number,
asio::error_code& ec)
{
this->get_service().add(this->get_implementation(), signal_number, ec);
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -234,7 +368,7 @@ public:
void remove(int signal_number)
{
asio::error_code ec;
this->get_service().remove(this->get_implementation(), signal_number, ec);
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
asio::detail::throw_error(ec, "remove");
}
@@ -253,7 +387,7 @@ public:
ASIO_SYNC_OP_VOID remove(int signal_number,
asio::error_code& ec)
{
this->get_service().remove(this->get_implementation(), signal_number, ec);
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -269,7 +403,7 @@ public:
void clear()
{
asio::error_code ec;
this->get_service().clear(this->get_implementation(), ec);
impl_.get_service().clear(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "clear");
}
@@ -284,7 +418,7 @@ public:
*/
ASIO_SYNC_OP_VOID clear(asio::error_code& ec)
{
this->get_service().clear(this->get_implementation(), ec);
impl_.get_service().clear(impl_.get_implementation(), ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -312,7 +446,7 @@ public:
void cancel()
{
asio::error_code ec;
this->get_service().cancel(this->get_implementation(), ec);
impl_.get_service().cancel(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel");
}
@@ -339,7 +473,7 @@ public:
*/
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
{
this->get_service().cancel(this->get_implementation(), ec);
impl_.get_service().cancel(impl_.get_implementation(), ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
@@ -364,28 +498,44 @@ public:
* int signal_number // Indicates which signal occurred.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename SignalHandler>
ASIO_INITFN_RESULT_TYPE(SignalHandler,
void (asio::error_code, int))
async_wait(ASIO_MOVE_ARG(SignalHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a SignalHandler.
ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
return this->get_service().async_wait(this->get_implementation(),
ASIO_MOVE_CAST(SignalHandler)(handler));
return async_initiate<SignalHandler, void (asio::error_code, int)>(
initiate_async_wait(), handler, this);
}
private:
// Disallow copying and assignment.
basic_signal_set(const basic_signal_set&) ASIO_DELETED;
basic_signal_set& operator=(const basic_signal_set&) ASIO_DELETED;
struct initiate_async_wait
{
template <typename SignalHandler>
void operator()(ASIO_MOVE_ARG(SignalHandler) handler,
basic_signal_set* self) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a SignalHandler.
ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
detail::non_const_lvalue<SignalHandler> handler2(handler);
self->impl_.get_service().async_wait(
self->impl_.get_implementation(), handler2.value,
self->impl_.get_implementation_executor());
}
};
detail::io_object_impl<detail::signal_set_service, Executor> impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#endif // ASIO_BASIC_SIGNAL_SET_HPP

View File

@@ -2,7 +2,7 @@
// basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -23,10 +23,6 @@
#include <ostream>
#include "asio/basic_socket_streambuf.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/stream_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
# include "asio/detail/variadic_templates.hpp"
@@ -36,8 +32,7 @@
// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
// : std::basic_iostream<char>(
// &this->detail::socket_iostream_base<
// Protocol ASIO_SVC_TARG, Clock,
// WaitTraits ASIO_SVC_TARG1>::streambuf_)
// Protocol, Clock, WaitTraits>::streambuf_)
// {
// if (rdbuf()->connect(x1, ..., xn) == 0)
// this->setstate(std::ios_base::failbit);
@@ -49,8 +44,7 @@
explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
: std::basic_iostream<char>( \
&this->detail::socket_iostream_base< \
Protocol ASIO_SVC_TARG, Clock, \
WaitTraits ASIO_SVC_TARG1>::streambuf_) \
Protocol, Clock, WaitTraits>::streambuf_) \
{ \
this->setf(std::ios_base::unitbuf); \
if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
@@ -85,8 +79,7 @@ namespace detail {
// A separate base class is used to ensure that the streambuf is initialised
// prior to the basic_socket_iostream's basic_iostream base class.
template <typename Protocol ASIO_SVC_TPARAM,
typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
template <typename Protocol, typename Clock, typename WaitTraits>
class socket_iostream_base
{
protected:
@@ -112,8 +105,7 @@ protected:
}
#endif // defined(ASIO_HAS_MOVE)
basic_socket_streambuf<Protocol ASIO_SVC_TARG,
Clock, WaitTraits ASIO_SVC_TARG1> streambuf_;
basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_;
};
} // namespace detail
@@ -122,17 +114,17 @@ protected:
#define ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
#if defined(ASIO_HAS_BOOST_DATE_TIME)
template <typename Protocol,
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = boost::posix_time::ptime,
typename WaitTraits = time_traits<Clock>
ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
#else
typename WaitTraits = time_traits<Clock> >
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock>
ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
#endif
typename WaitTraits = wait_traits<Clock> >
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
class basic_socket_iostream;
#endif // !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
@@ -143,22 +135,23 @@ template <typename Protocol,
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock> >
#else // defined(GENERATING_DOCUMENTATION)
template <typename Protocol ASIO_SVC_TPARAM,
typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
template <typename Protocol, typename Clock, typename WaitTraits>
#endif // defined(GENERATING_DOCUMENTATION)
class basic_socket_iostream
: private detail::socket_iostream_base<Protocol
ASIO_SVC_TARG, Clock, WaitTraits ASIO_SVC_TARG1>,
: private detail::socket_iostream_base<Protocol, Clock, WaitTraits>,
public std::basic_iostream<char>
{
private:
// These typedefs are intended keep this class's implementation independent
// of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
#if defined(ASIO_HAS_BOOST_DATE_TIME)
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef WaitTraits traits_helper;
#else
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
#endif
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
public:
/// The protocol type.
@@ -195,8 +188,7 @@ public:
basic_socket_iostream()
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::streambuf_)
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
}
@@ -205,12 +197,10 @@ public:
/// Construct a basic_socket_iostream from the supplied socket.
explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
: detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>(std::move(s)),
Protocol, Clock, WaitTraits>(std::move(s)),
std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::streambuf_)
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
}
@@ -220,13 +210,11 @@ public:
/// Move-construct a basic_socket_iostream from another.
basic_socket_iostream(basic_socket_iostream&& other)
: detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>(std::move(other)),
Protocol, Clock, WaitTraits>(std::move(other)),
std::basic_iostream<char>(std::move(other))
{
this->set_rdbuf(&this->detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::streambuf_);
Protocol, Clock, WaitTraits>::streambuf_);
}
/// Move-assign a basic_socket_iostream from another.
@@ -234,8 +222,7 @@ public:
{
std::basic_iostream<char>::operator=(std::move(other));
detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::operator=(std::move(other));
Protocol, Clock, WaitTraits>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_STD_IOSTREAM_MOVE)
@@ -256,8 +243,7 @@ public:
explicit basic_socket_iostream(T... x)
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::streambuf_)
Protocol, Clock, WaitTraits>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
if (rdbuf()->connect(x...) == 0)
@@ -295,18 +281,15 @@ public:
}
/// Return a pointer to the underlying streambuf.
basic_socket_streambuf<Protocol ASIO_SVC_TARG,
Clock, WaitTraits ASIO_SVC_TARG1>* rdbuf() const
basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const
{
return const_cast<basic_socket_streambuf<Protocol ASIO_SVC_TARG,
Clock, WaitTraits ASIO_SVC_TARG1>*>(
return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(
&this->detail::socket_iostream_base<
Protocol ASIO_SVC_TARG, Clock,
WaitTraits ASIO_SVC_TARG1>::streambuf_);
Protocol, Clock, WaitTraits>::streambuf_);
}
/// Get a reference to the underlying socket.
basic_socket<Protocol ASIO_SVC_TARG>& socket()
basic_socket<Protocol>& socket()
{
return rdbuf()->socket();
}

View File

@@ -2,7 +2,7 @@
// basic_socket_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -28,19 +28,14 @@
#include "asio/detail/throw_error.hpp"
#include "asio/io_context.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/stream_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#if defined(ASIO_HAS_BOOST_DATE_TIME)
# if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/deadline_timer_service.hpp"
# else // defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/detail/deadline_timer_service.hpp"
# endif // defined(ASIO_ENABLE_OLD_SERVICES)
#else
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
# include "asio/detail/deadline_timer_service.hpp"
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
# include "asio/steady_timer.hpp"
#endif
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
@@ -52,7 +47,7 @@
// {
// init_buffers();
// typedef typename Protocol::resolver resolver_type;
// resolver_type resolver(socket().get_executor().context());
// resolver_type resolver(socket().get_executor());
// connect_to_endpoints(
// resolver.resolve(x1, ..., xn, ec_));
// return !ec_ ? this : 0;
@@ -65,7 +60,7 @@
{ \
init_buffers(); \
typedef typename Protocol::resolver resolver_type; \
resolver_type resolver(socket().get_executor().context()); \
resolver_type resolver(socket().get_executor()); \
connect_to_endpoints( \
resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
return !ec_ ? this : 0; \
@@ -74,10 +69,6 @@
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
#if !defined(ASIO_ENABLE_OLD_SERVICES)
# define ASIO_SVC_T1 detail::deadline_timer_service<traits_helper>
#endif // !defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
@@ -121,17 +112,17 @@ protected:
#define ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
#if defined(ASIO_HAS_BOOST_DATE_TIME)
template <typename Protocol,
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = boost::posix_time::ptime,
typename WaitTraits = time_traits<Clock>
ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
#else
typename WaitTraits = time_traits<Clock> >
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock>
ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
#endif
typename WaitTraits = wait_traits<Clock> >
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
class basic_socket_streambuf;
#endif // !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
@@ -142,27 +133,29 @@ template <typename Protocol,
typename Clock = chrono::steady_clock,
typename WaitTraits = wait_traits<Clock> >
#else // defined(GENERATING_DOCUMENTATION)
template <typename Protocol ASIO_SVC_TPARAM,
typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
template <typename Protocol, typename Clock, typename WaitTraits>
#endif // defined(GENERATING_DOCUMENTATION)
class basic_socket_streambuf
: public std::streambuf,
private detail::socket_streambuf_io_context,
private detail::socket_streambuf_buffers,
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
private basic_socket<Protocol ASIO_SVC_TARG>
private basic_socket<Protocol>
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
public basic_socket<Protocol ASIO_SVC_TARG>
public basic_socket<Protocol>
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
{
private:
// These typedefs are intended keep this class's implementation independent
// of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
#if defined(ASIO_HAS_BOOST_DATE_TIME)
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef WaitTraits traits_helper;
#else
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
#endif
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
public:
/// The protocol type.
@@ -198,7 +191,7 @@ public:
/// Construct a basic_socket_streambuf without establishing a connection.
basic_socket_streambuf()
: detail::socket_streambuf_io_context(new io_context),
basic_socket<Protocol ASIO_SVC_TARG>(*default_io_context_),
basic_socket<Protocol>(*default_io_context_),
expiry_time_(max_expiry_time())
{
init_buffers();
@@ -208,7 +201,7 @@ public:
/// Construct a basic_socket_streambuf from the supplied socket.
explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
: detail::socket_streambuf_io_context(0),
basic_socket<Protocol ASIO_SVC_TARG>(std::move(s)),
basic_socket<Protocol>(std::move(s)),
expiry_time_(max_expiry_time())
{
init_buffers();
@@ -217,7 +210,7 @@ public:
/// Move-construct a basic_socket_streambuf from another.
basic_socket_streambuf(basic_socket_streambuf&& other)
: detail::socket_streambuf_io_context(other),
basic_socket<Protocol ASIO_SVC_TARG>(std::move(other.socket())),
basic_socket<Protocol>(std::move(other.socket())),
ec_(other.ec_),
expiry_time_(other.expiry_time_)
{
@@ -290,7 +283,7 @@ public:
{
init_buffers();
typedef typename Protocol::resolver resolver_type;
resolver_type resolver(socket().get_executor().context());
resolver_type resolver(socket().get_executor());
connect_to_endpoints(resolver.resolve(x..., ec_));
return !ec_ ? this : 0;
}
@@ -313,7 +306,7 @@ public:
}
/// Get a reference to the underlying socket.
basic_socket<Protocol ASIO_SVC_TARG>& socket()
basic_socket<Protocol>& socket()
{
return *this;
}
@@ -666,11 +659,14 @@ private:
// Helper function to get the maximum expiry time.
static time_point max_expiry_time()
{
#if defined(ASIO_HAS_BOOST_DATE_TIME)
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
return boost::posix_time::pos_infin;
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
return (time_point::max)();
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
}
enum { putback_max = 8 };
@@ -682,10 +678,6 @@ private:
#include "asio/detail/pop_options.hpp"
#if !defined(ASIO_ENABLE_OLD_SERVICES)
# undef ASIO_SVC_T1
#endif // !defined(ASIO_ENABLE_OLD_SERVICES)
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
# undef ASIO_PRIVATE_CONNECT_DEF
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)

View File

@@ -2,7 +2,7 @@
// basic_stream_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -20,17 +20,23 @@
#include "asio/async_result.hpp"
#include "asio/basic_socket.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/stream_socket_service.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
#if !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
#define ASIO_BASIC_STREAM_SOCKET_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Protocol, typename Executor = executor>
class basic_stream_socket;
#endif // !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
/// Provides stream-oriented socket functionality.
/**
* The basic_stream_socket class template provides asynchronous and blocking
@@ -43,18 +49,28 @@ namespace asio {
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template <typename Protocol
ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>)>
template <typename Protocol, typename Executor>
class basic_stream_socket
: public basic_socket<Protocol ASIO_SVC_TARG>
: public basic_socket<Protocol, Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the socket type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The socket type when rebound to the specified executor.
typedef basic_stream_socket<Protocol, Executor1> other;
};
/// The native representation of a socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_socket<
Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type;
typedef typename basic_socket<Protocol,
Executor>::native_handle_type native_handle_type;
#endif
/// The protocol type.
@@ -69,11 +85,30 @@ public:
* needs to be opened and then connected or accepted before data can be sent
* or received on it.
*
* @param io_context The io_context object that the stream socket will use to
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
explicit basic_stream_socket(asio::io_context& io_context)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context)
explicit basic_stream_socket(const executor_type& ex)
: basic_socket<Protocol, Executor>(ex)
{
}
/// Construct a basic_stream_socket without opening it.
/**
* This constructor creates a stream socket without opening it. The socket
* needs to be opened and then connected or accepted before data can be sent
* or received on it.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*/
template <typename ExecutionContext>
explicit basic_stream_socket(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context)
{
}
@@ -82,16 +117,37 @@ public:
* This constructor creates and opens a stream socket. The socket needs to be
* connected or accepted before data can be sent or received on it.
*
* @param io_context The io_context object that the stream socket will use to
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_context& io_context,
const protocol_type& protocol)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol)
basic_stream_socket(const executor_type& ex, const protocol_type& protocol)
: basic_socket<Protocol, Executor>(ex, protocol)
{
}
/// Construct and open a basic_stream_socket.
/**
* This constructor creates and opens a stream socket. The socket needs to be
* connected or accepted before data can be sent or received on it.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol)
{
}
@@ -102,7 +158,7 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param io_context The io_context object that the stream socket will use to
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the stream
@@ -110,9 +166,33 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_context& io_context,
const endpoint_type& endpoint)
: basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint)
basic_stream_socket(const executor_type& ex, const endpoint_type& endpoint)
: basic_socket<Protocol, Executor>(ex, endpoint)
{
}
/// Construct a basic_stream_socket, opening it and binding it to the given
/// local endpoint.
/**
* This constructor creates a stream socket and automatically opens it bound
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the stream
* socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, endpoint)
{
}
@@ -121,7 +201,7 @@ public:
* This constructor creates a stream socket object to hold an existing native
* socket.
*
* @param io_context The io_context object that the stream socket will use to
* @param ex The I/O executor that the socket will use, by default, to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
@@ -130,10 +210,34 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
basic_stream_socket(asio::io_context& io_context,
basic_stream_socket(const executor_type& ex,
const protocol_type& protocol, const native_handle_type& native_socket)
: basic_socket<Protocol ASIO_SVC_TARG>(
io_context, protocol, native_socket)
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
{
}
/// Construct a basic_stream_socket on an existing native socket.
/**
* This constructor creates a stream socket object to hold an existing native
* socket.
*
* @param context An execution context which provides the I/O executor that
* the socket will use, by default, to dispatch handlers for any asynchronous
* operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
{
}
@@ -146,10 +250,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_socket(io_context&) constructor.
* constructed using the @c basic_stream_socket(const executor_type&)
* constructor.
*/
basic_stream_socket(basic_stream_socket&& other)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -161,11 +266,12 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_socket(io_context&) constructor.
* constructed using the @c basic_stream_socket(const executor_type&)
* constructor.
*/
basic_stream_socket& operator=(basic_stream_socket&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
@@ -178,13 +284,16 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_socket(io_context&) constructor.
* constructed using the @c basic_stream_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
basic_stream_socket(
basic_stream_socket<Protocol1 ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
: basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
template <typename Protocol1, typename Executor1>
basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value
>::type* = 0)
: basic_socket<Protocol, Executor>(std::move(other))
{
}
@@ -196,14 +305,17 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_socket(io_context&) constructor.
* constructed using the @c basic_stream_socket(const executor_type&)
* constructor.
*/
template <typename Protocol1 ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_stream_socket>::type& operator=(
basic_stream_socket<Protocol1 ASIO_SVC_TARG1>&& other)
template <typename Protocol1, typename Executor1>
typename enable_if<
is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value,
basic_stream_socket&
>::type operator=(basic_stream_socket<Protocol1, Executor1>&& other)
{
basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
basic_socket<Protocol, Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -246,8 +358,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -284,8 +396,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "send");
return s;
}
@@ -312,8 +424,8 @@ public:
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().send(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous send.
@@ -334,9 +446,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
@@ -357,24 +469,10 @@ public:
async_send(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(
this->get_implementation(), buffers, 0,
ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(
this->get_implementation(), buffers, 0,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous send.
@@ -397,9 +495,9 @@ public:
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
@@ -421,24 +519,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(
this->get_implementation(), buffers, flags,
ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(
this->get_implementation(), buffers, flags,
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this, buffers, flags);
}
/// Receive some data on the socket.
@@ -473,8 +556,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -514,8 +597,8 @@ public:
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
asio::detail::throw_error(ec, "receive");
return s;
}
@@ -542,8 +625,8 @@ public:
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->get_service().receive(
this->get_implementation(), buffers, flags, ec);
return this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, flags, ec);
}
/// Start an asynchronous receive.
@@ -564,9 +647,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref async_read function if you need to ensure
@@ -589,22 +672,10 @@ public:
async_receive(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Start an asynchronous receive.
@@ -627,9 +698,9 @@ public:
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref async_read function if you need to ensure
@@ -653,22 +724,9 @@ public:
socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, flags, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this, buffers, flags);
}
/// Write some data to the socket.
@@ -702,8 +760,8 @@ public:
std::size_t write_some(const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().send(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "write_some");
return s;
}
@@ -728,7 +786,8 @@ public:
std::size_t write_some(const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return this->get_service().send(this->get_implementation(), buffers, 0, ec);
return this->impl_.get_service().send(
this->impl_.get_implementation(), buffers, 0, ec);
}
/// Start an asynchronous write.
@@ -749,9 +808,9 @@ public:
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The write operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
@@ -772,22 +831,10 @@ public:
async_write_some(const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_send(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WriteHandler,
void (asio::error_code, std::size_t)>(
initiate_async_send(), handler, this,
buffers, socket_base::message_flags(0));
}
/// Read some data from the socket.
@@ -822,8 +869,8 @@ public:
std::size_t read_some(const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, ec);
std::size_t s = this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, 0, ec);
asio::detail::throw_error(ec, "read_some");
return s;
}
@@ -849,8 +896,8 @@ public:
std::size_t read_some(const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return this->get_service().receive(
this->get_implementation(), buffers, 0, ec);
return this->impl_.get_service().receive(
this->impl_.get_implementation(), buffers, 0, ec);
}
/// Start an asynchronous read.
@@ -871,9 +918,9 @@ public:
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read function if you need to ensure that the
@@ -895,23 +942,48 @@ public:
async_read_some(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
this->get_service().async_receive(this->get_implementation(),
buffers, 0, init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<ReadHandler,
void (asio::error_code, std::size_t)>(
initiate_async_receive(), handler, this,
buffers, socket_base::message_flags(0));
}
private:
struct initiate_async_send
{
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
basic_stream_socket* self, const ConstBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self->impl_.get_service().async_send(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
struct initiate_async_receive
{
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
basic_stream_socket* self, const MutableBufferSequence& buffers,
socket_base::message_flags flags) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self->impl_.get_service().async_receive(
self->impl_.get_implementation(), buffers, flags,
handler2.value, self->impl_.get_implementation_executor());
}
};
};
} // namespace asio

View File

@@ -2,7 +2,7 @@
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// basic_streambuf_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// basic_waitable_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,26 +17,20 @@
#include "asio/detail/config.hpp"
#include <cstddef>
#include "asio/basic_io_object.hpp"
#include "asio/detail/chrono_time_traits.hpp"
#include "asio/detail/deadline_timer_service.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/io_object_impl.hpp"
#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/executor.hpp"
#include "asio/wait_traits.hpp"
#if defined(ASIO_HAS_MOVE)
# include <utility>
#endif // defined(ASIO_HAS_MOVE)
#if defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/waitable_timer_service.hpp"
#else // defined(ASIO_ENABLE_OLD_SERVICES)
# include "asio/detail/chrono_time_traits.hpp"
# include "asio/detail/deadline_timer_service.hpp"
# define ASIO_SVC_T \
detail::deadline_timer_service< \
detail::chrono_time_traits<Clock, WaitTraits> >
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#include "asio/detail/push_options.hpp"
namespace asio {
@@ -46,8 +40,8 @@ namespace asio {
// Forward declaration with defaulted arguments.
template <typename Clock,
typename WaitTraits = asio::wait_traits<Clock>
ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)>
typename WaitTraits = asio::wait_traits<Clock>,
typename Executor = executor>
class basic_waitable_timer;
#endif // !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
@@ -75,7 +69,7 @@ class basic_waitable_timer;
* Performing a blocking wait (C++11):
* @code
* // Construct a timer without setting an expiry time.
* asio::steady_timer timer(io_context);
* asio::steady_timer timer(my_context);
*
* // Set an expiry time relative to now.
* timer.expires_after(std::chrono::seconds(5));
@@ -98,7 +92,7 @@ class basic_waitable_timer;
* ...
*
* // Construct a timer with an absolute expiry time.
* asio::steady_timer timer(io_context,
* asio::steady_timer timer(my_context,
* std::chrono::steady_clock::now() + std::chrono::seconds(60));
*
* // Start an asynchronous wait.
@@ -144,13 +138,12 @@ class basic_waitable_timer;
* @li If a wait handler is cancelled, the asio::error_code passed to
* it contains the value asio::error::operation_aborted.
*/
template <typename Clock, typename WaitTraits ASIO_SVC_TPARAM>
template <typename Clock, typename WaitTraits, typename Executor>
class basic_waitable_timer
: ASIO_SVC_ACCESS basic_io_object<ASIO_SVC_T>
{
public:
/// The type of the executor associated with the object.
typedef io_context::executor_type executor_type;
typedef Executor executor_type;
/// The clock type.
typedef Clock clock_type;
@@ -170,11 +163,30 @@ public:
* expires_at() or expires_after() functions must be called to set an expiry
* time before the timer can be waited on.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*/
explicit basic_waitable_timer(asio::io_context& io_context)
: basic_io_object<ASIO_SVC_T>(io_context)
explicit basic_waitable_timer(const executor_type& ex)
: impl_(ex)
{
}
/// Constructor.
/**
* This constructor creates a timer without setting an expiry time. The
* expires_at() or expires_after() functions must be called to set an expiry
* time before the timer can be waited on.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*/
template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
}
@@ -182,18 +194,41 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor object that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
basic_waitable_timer(asio::io_context& io_context,
const time_point& expiry_time)
: basic_io_object<ASIO_SVC_T>(io_context)
basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)
: impl_(ex)
{
asio::error_code ec;
this->get_service().expires_at(this->get_implementation(), expiry_time, ec);
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
}
/// Constructor to set a particular expiry time as an absolute time.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context,
const time_point& expiry_time,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
}
@@ -201,19 +236,43 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
* @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
* @param ex The I/O executor that the timer will use, by default, to
* dispatch handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
basic_waitable_timer(asio::io_context& io_context,
const duration& expiry_time)
: basic_io_object<ASIO_SVC_T>(io_context)
basic_waitable_timer(const executor_type& ex, const duration& expiry_time)
: impl_(ex)
{
asio::error_code ec;
this->get_service().expires_after(
this->get_implementation(), expiry_time, ec);
impl_.get_service().expires_after(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_after");
}
/// Constructor to set a particular expiry time relative to now.
/**
* This constructor creates a timer and sets the expiry time.
*
* @param context An execution context which provides the I/O executor that
* the timer will use, by default, to dispatch handlers for any asynchronous
* operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context,
const duration& expiry_time,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0)
: impl_(context)
{
asio::error_code ec;
impl_.get_service().expires_after(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_after");
}
@@ -226,10 +285,11 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_waitable_timer(io_context&) constructor.
* constructed using the @c basic_waitable_timer(const executor_type&)
* constructor.
*/
basic_waitable_timer(basic_waitable_timer&& other)
: basic_io_object<ASIO_SVC_T>(std::move(other))
: impl_(std::move(other.impl_))
{
}
@@ -242,11 +302,12 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_waitable_timer(io_context&) constructor.
* constructed using the @c basic_waitable_timer(const executor_type&)
* constructor.
*/
basic_waitable_timer& operator=(basic_waitable_timer&& other)
{
basic_io_object<ASIO_SVC_T>::operator=(std::move(other));
impl_ = std::move(other.impl_);
return *this;
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
@@ -260,45 +321,11 @@ public:
{
}
#if defined(ASIO_ENABLE_OLD_SERVICES)
// These functions are provided by basic_io_object<>.
#else // defined(ASIO_ENABLE_OLD_SERVICES)
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
/**
* This function may be used to obtain the io_context object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_context object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_context& get_io_context()
{
return basic_io_object<ASIO_SVC_T>::get_io_context();
}
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
/**
* This function may be used to obtain the io_context object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_context object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_context& get_io_service()
{
return basic_io_object<ASIO_SVC_T>::get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)
/// Get the executor associated with the object.
executor_type get_executor() ASIO_NOEXCEPT
{
return basic_io_object<ASIO_SVC_T>::get_executor();
return impl_.get_executor();
}
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
/// Cancel any asynchronous operations that are waiting on the timer.
/**
@@ -325,7 +352,7 @@ public:
std::size_t cancel()
{
asio::error_code ec;
std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel");
return s;
}
@@ -356,7 +383,7 @@ public:
*/
std::size_t cancel(asio::error_code& ec)
{
return this->get_service().cancel(this->get_implementation(), ec);
return impl_.get_service().cancel(impl_.get_implementation(), ec);
}
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -387,8 +414,8 @@ public:
std::size_t cancel_one()
{
asio::error_code ec;
std::size_t s = this->get_service().cancel_one(
this->get_implementation(), ec);
std::size_t s = impl_.get_service().cancel_one(
impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "cancel_one");
return s;
}
@@ -421,7 +448,7 @@ public:
*/
std::size_t cancel_one(asio::error_code& ec)
{
return this->get_service().cancel_one(this->get_implementation(), ec);
return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
}
/// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
@@ -432,7 +459,7 @@ public:
*/
time_point expires_at() const
{
return this->get_service().expires_at(this->get_implementation());
return impl_.get_service().expires_at(impl_.get_implementation());
}
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -443,7 +470,7 @@ public:
*/
time_point expiry() const
{
return this->get_service().expiry(this->get_implementation());
return impl_.get_service().expiry(impl_.get_implementation());
}
/// Set the timer's expiry time as an absolute time.
@@ -471,8 +498,8 @@ public:
std::size_t expires_at(const time_point& expiry_time)
{
asio::error_code ec;
std::size_t s = this->get_service().expires_at(
this->get_implementation(), expiry_time, ec);
std::size_t s = impl_.get_service().expires_at(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_at");
return s;
}
@@ -504,8 +531,8 @@ public:
std::size_t expires_at(const time_point& expiry_time,
asio::error_code& ec)
{
return this->get_service().expires_at(
this->get_implementation(), expiry_time, ec);
return impl_.get_service().expires_at(
impl_.get_implementation(), expiry_time, ec);
}
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -534,8 +561,8 @@ public:
std::size_t expires_after(const duration& expiry_time)
{
asio::error_code ec;
std::size_t s = this->get_service().expires_after(
this->get_implementation(), expiry_time, ec);
std::size_t s = impl_.get_service().expires_after(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_after");
return s;
}
@@ -548,7 +575,7 @@ public:
*/
duration expires_from_now() const
{
return this->get_service().expires_from_now(this->get_implementation());
return impl_.get_service().expires_from_now(impl_.get_implementation());
}
/// (Deprecated: Use expires_after().) Set the timer's expiry time relative
@@ -577,8 +604,8 @@ public:
std::size_t expires_from_now(const duration& expiry_time)
{
asio::error_code ec;
std::size_t s = this->get_service().expires_from_now(
this->get_implementation(), expiry_time, ec);
std::size_t s = impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
asio::detail::throw_error(ec, "expires_from_now");
return s;
}
@@ -609,8 +636,8 @@ public:
std::size_t expires_from_now(const duration& expiry_time,
asio::error_code& ec)
{
return this->get_service().expires_from_now(
this->get_implementation(), expiry_time, ec);
return impl_.get_service().expires_from_now(
impl_.get_implementation(), expiry_time, ec);
}
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -624,7 +651,7 @@ public:
void wait()
{
asio::error_code ec;
this->get_service().wait(this->get_implementation(), ec);
impl_.get_service().wait(impl_.get_implementation(), ec);
asio::detail::throw_error(ec, "wait");
}
@@ -637,7 +664,7 @@ public:
*/
void wait(asio::error_code& ec)
{
this->get_service().wait(this->get_implementation(), ec);
impl_.get_service().wait(impl_.get_implementation(), ec);
}
/// Start an asynchronous wait on the timer.
@@ -660,31 +687,17 @@ public:
* const asio::error_code& error // Result of operation.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*/
template <typename WaitHandler>
ASIO_INITFN_RESULT_TYPE(WaitHandler,
void (asio::error_code))
async_wait(ASIO_MOVE_ARG(WaitHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WaitHandler.
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
#if defined(ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_wait(this->get_implementation(),
ASIO_MOVE_CAST(WaitHandler)(handler));
#else // defined(ASIO_ENABLE_OLD_SERVICES)
async_completion<WaitHandler,
void (asio::error_code)> init(handler);
this->get_service().async_wait(this->get_implementation(),
init.completion_handler);
return init.result.get();
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
return async_initiate<WaitHandler, void (asio::error_code)>(
initiate_async_wait(), handler, this);
}
private:
@@ -692,14 +705,32 @@ private:
basic_waitable_timer(const basic_waitable_timer&) ASIO_DELETED;
basic_waitable_timer& operator=(
const basic_waitable_timer&) ASIO_DELETED;
struct initiate_async_wait
{
template <typename WaitHandler>
void operator()(ASIO_MOVE_ARG(WaitHandler) handler,
basic_waitable_timer* self) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WaitHandler.
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
detail::non_const_lvalue<WaitHandler> handler2(handler);
self->impl_.get_service().async_wait(
self->impl_.get_implementation(), handler2.value,
self->impl_.get_implementation_executor());
}
};
detail::io_object_impl<
detail::deadline_timer_service<
detail::chrono_time_traits<Clock, WaitTraits> >,
executor_type > impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#if !defined(ASIO_ENABLE_OLD_SERVICES)
# undef ASIO_SVC_T
#endif // !defined(ASIO_ENABLE_OLD_SERVICES)
#endif // ASIO_BASIC_WAITABLE_TIMER_HPP

View File

@@ -2,7 +2,7 @@
// bind_executor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -547,37 +547,6 @@ private:
async_result<T, Signature> target_;
};
#if !defined(ASIO_NO_DEPRECATED)
template <typename T, typename Executor, typename Signature>
struct handler_type<executor_binder<T, Executor>, Signature>
{
typedef executor_binder<
typename handler_type<T, Signature>::type, Executor> type;
};
template <typename T, typename Executor>
class async_result<executor_binder<T, Executor> >
{
public:
typedef typename async_result<T>::type type;
explicit async_result(executor_binder<T, Executor>& b)
: target_(b.get())
{
}
type get()
{
return target_.get();
}
private:
async_result<T> target_;
};
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename T, typename Executor, typename Allocator>
struct associated_allocator<executor_binder<T, Executor>, Allocator>
{

View File

@@ -2,7 +2,7 @@
// buffer.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -23,7 +23,7 @@
#include <string>
#include <vector>
#include "asio/detail/array_fwd.hpp"
#include "asio/detail/is_buffer_sequence.hpp"
#include "asio/detail/memory.hpp"
#include "asio/detail/string_view.hpp"
#include "asio/detail/throw_exception.hpp"
#include "asio/detail/type_traits.hpp"
@@ -346,41 +346,6 @@ public:
#endif // !defined(ASIO_NO_DEPRECATED)
/// Trait to determine whether a type satisfies the MutableBufferSequence
/// requirements.
template <typename T>
struct is_mutable_buffer_sequence
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_buffer_sequence<T, mutable_buffer>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
/// Trait to determine whether a type satisfies the ConstBufferSequence
/// requirements.
template <typename T>
struct is_const_buffer_sequence
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_buffer_sequence<T, const_buffer>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
/// Trait to determine whether a type satisfies the DynamicBuffer requirements.
template <typename T>
struct is_dynamic_buffer
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_dynamic_buffer<T>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
/// (Deprecated: Use the socket/descriptor wait() and async_wait() member
/// functions.) An implementation of both the ConstBufferSequence and
/// MutableBufferSequence concepts to represent a null buffer sequence.
@@ -417,29 +382,45 @@ private:
/*@{*/
/// Get an iterator to the first element in a buffer sequence.
inline const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b)
template <typename MutableBuffer>
inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
typename enable_if<
is_convertible<const MutableBuffer*, const mutable_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return &b;
return static_cast<const mutable_buffer*>(detail::addressof(b));
}
/// Get an iterator to the first element in a buffer sequence.
inline const const_buffer* buffer_sequence_begin(const const_buffer& b)
template <typename ConstBuffer>
inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
typename enable_if<
is_convertible<const ConstBuffer*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return &b;
return static_cast<const const_buffer*>(detail::addressof(b));
}
#if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
/// Get an iterator to the first element in a buffer sequence.
template <typename C>
inline auto buffer_sequence_begin(C& c) -> decltype(c.begin())
inline auto buffer_sequence_begin(C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())
{
return c.begin();
}
/// Get an iterator to the first element in a buffer sequence.
template <typename C>
inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin())
inline auto buffer_sequence_begin(const C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())
{
return c.begin();
}
@@ -447,13 +428,21 @@ inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin())
#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
template <typename C>
inline typename C::iterator buffer_sequence_begin(C& c)
inline typename C::iterator buffer_sequence_begin(C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return c.begin();
}
template <typename C>
inline typename C::const_iterator buffer_sequence_begin(const C& c)
inline typename C::const_iterator buffer_sequence_begin(const C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return c.begin();
}
@@ -470,29 +459,45 @@ inline typename C::const_iterator buffer_sequence_begin(const C& c)
/*@{*/
/// Get an iterator to one past the end element in a buffer sequence.
inline const mutable_buffer* buffer_sequence_end(const mutable_buffer& b)
template <typename MutableBuffer>
inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
typename enable_if<
is_convertible<const MutableBuffer*, const mutable_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return &b + 1;
return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
}
/// Get an iterator to one past the end element in a buffer sequence.
inline const const_buffer* buffer_sequence_end(const const_buffer& b)
template <typename ConstBuffer>
inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
typename enable_if<
is_convertible<const ConstBuffer*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return &b + 1;
return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
}
#if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
/// Get an iterator to one past the end element in a buffer sequence.
template <typename C>
inline auto buffer_sequence_end(C& c) -> decltype(c.end())
inline auto buffer_sequence_end(C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())
{
return c.end();
}
/// Get an iterator to one past the end element in a buffer sequence.
template <typename C>
inline auto buffer_sequence_end(const C& c) -> decltype(c.end())
inline auto buffer_sequence_end(const C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())
{
return c.end();
}
@@ -500,13 +505,21 @@ inline auto buffer_sequence_end(const C& c) -> decltype(c.end())
#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
template <typename C>
inline typename C::iterator buffer_sequence_end(C& c)
inline typename C::iterator buffer_sequence_end(C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return c.end();
}
template <typename C>
inline typename C::const_iterator buffer_sequence_end(const C& c)
inline typename C::const_iterator buffer_sequence_end(const C& c,
typename enable_if<
!is_convertible<const C*, const mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) ASIO_NOEXCEPT
{
return c.end();
}
@@ -706,7 +719,7 @@ public:
void operator()()
{
*iter_;
(void)*iter_;
}
private:
@@ -1403,7 +1416,7 @@ inline ASIO_MUTABLE_BUFFER buffer(
);
}
/// Create a new non-modifiable buffer that represents the given string.
/// Create a new modifiable buffer that represents the given string.
/**
* @returns A mutable_buffer value equivalent to:
* @code mutable_buffer(
@@ -1475,7 +1488,7 @@ inline ASIO_CONST_BUFFER buffer(
);
}
#if defined(ASIO_HAS_STD_STRING_VIEW) \
#if defined(ASIO_HAS_STRING_VIEW) \
|| defined(GENERATING_DOCUMENTATION)
/// Create a new modifiable buffer that represents the given string_view.
@@ -1520,7 +1533,7 @@ inline ASIO_CONST_BUFFER buffer(
);
}
#endif // defined(ASIO_HAS_STD_STRING_VIEW)
#endif // defined(ASIO_HAS_STRING_VIEW)
// || defined(GENERATING_DOCUMENTATION)
/*@}*/
@@ -1533,19 +1546,23 @@ template <typename Elem, typename Traits, typename Allocator>
class dynamic_string_buffer
{
public:
/// The type used to represent the input sequence as a list of buffers.
/// The type used to represent a sequence of constant buffers that refers to
/// the underlying memory.
typedef ASIO_CONST_BUFFER const_buffers_type;
/// The type used to represent the output sequence as a list of buffers.
/// The type used to represent a sequence of mutable buffers that refers to
/// the underlying memory.
typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
/// Construct a dynamic buffer from a string.
/**
* @param s The string to be used as backing storage for the dynamic buffer.
* Any existing data in the string is treated as the dynamic buffer's input
* sequence. The object stores a reference to the string and the user is
* responsible for ensuring that the string object remains valid until the
* dynamic_string_buffer object is destroyed.
* The object stores a reference to the string and the user is responsible
* for ensuring that the string object remains valid while the
* dynamic_string_buffer object, and copies of the object, are in use.
*
* @b DynamicBuffer_v1: Any existing data in the string is treated as the
* dynamic buffer's input sequence.
*
* @param maximum_size Specifies a maximum size for the buffer, in bytes.
*/
@@ -1553,64 +1570,131 @@ public:
std::size_t maximum_size =
(std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
: string_(s),
size_(string_.size()),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_((std::numeric_limits<std::size_t>::max)()),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(maximum_size)
{
}
/// @b DynamicBuffer_v2: Copy construct a dynamic buffer.
dynamic_string_buffer(const dynamic_string_buffer& other) ASIO_NOEXCEPT
: string_(other.string_),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_(other.size_),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(other.max_size_)
{
}
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move construct a dynamic buffer.
dynamic_string_buffer(dynamic_string_buffer&& other) ASIO_NOEXCEPT
: string_(other.string_),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_(other.size_),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(other.max_size_)
{
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Get the size of the input sequence.
/// @b DynamicBuffer_v1: Get the size of the input sequence.
/// @b DynamicBuffer_v2: Get the current size of the underlying memory.
/**
* @returns @b DynamicBuffer_v1 The current size of the input sequence.
* @b DynamicBuffer_v2: The current size of the underlying string if less than
* max_size(). Otherwise returns max_size().
*/
std::size_t size() const ASIO_NOEXCEPT
{
return size_;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
if (size_ != (std::numeric_limits<std::size_t>::max)())
return size_;
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
return (std::min)(string_.size(), max_size());
}
/// Get the maximum size of the dynamic buffer.
/**
* @returns The allowed maximum of the sum of the sizes of the input sequence
* and output sequence.
* @returns The allowed maximum size of the underlying memory.
*/
std::size_t max_size() const ASIO_NOEXCEPT
{
return max_size_;
}
/// Get the current capacity of the dynamic buffer.
/// Get the maximum size that the buffer may grow to without triggering
/// reallocation.
/**
* @returns The current total capacity of the buffer, i.e. for both the input
* sequence and output sequence.
* @returns The current capacity of the underlying string if less than
* max_size(). Otherwise returns max_size().
*/
std::size_t capacity() const ASIO_NOEXCEPT
{
return string_.capacity();
return (std::min)(string_.capacity(), max_size());
}
/// Get a list of buffers that represents the input sequence.
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// @b DynamicBuffer_v1: Get a list of buffers that represents the input
/// sequence.
/**
* @returns An object of type @c const_buffers_type that satisfies
* ConstBufferSequence requirements, representing the basic_string memory in
* input sequence.
* the input sequence.
*
* @note The returned object is invalidated by any @c dynamic_string_buffer
* or @c basic_string member function that modifies the input sequence or
* output sequence.
* or @c basic_string member function that resizes or erases the string.
*/
const_buffers_type data() const ASIO_NOEXCEPT
{
return const_buffers_type(asio::buffer(string_, size_));
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Get a list of buffers that represents the output sequence, with the given
/// size.
/// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
/// underlying memory.
/**
* @param pos Position of the first byte to represent in the buffer sequence
*
* @param n The number of bytes to return in the buffer sequence. If the
* underlying memory is shorter, the buffer sequence represents as many bytes
* as are available.
*
* @returns An object of type @c mutable_buffers_type that satisfies
* MutableBufferSequence requirements, representing the basic_string memory.
*
* @note The returned object is invalidated by any @c dynamic_string_buffer
* or @c basic_string member function that resizes or erases the string.
*/
mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
{
return mutable_buffers_type(asio::buffer(
asio::buffer(string_, max_size_) + pos, n));
}
/// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
/// underlying memory.
/**
* @param pos Position of the first byte to represent in the buffer sequence
*
* @param n The number of bytes to return in the buffer sequence. If the
* underlying memory is shorter, the buffer sequence represents as many bytes
* as are available.
*
* @note The returned object is invalidated by any @c dynamic_string_buffer
* or @c basic_string member function that resizes or erases the string.
*/
const_buffers_type data(std::size_t pos,
std::size_t n) const ASIO_NOEXCEPT
{
return const_buffers_type(asio::buffer(
asio::buffer(string_, max_size_) + pos, n));
}
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// @b DynamicBuffer_v1: Get a list of buffers that represents the output
/// sequence, with the given size.
/**
* Ensures that the output sequence can accommodate @c n bytes, resizing the
* basic_string object as necessary.
@@ -1627,18 +1711,22 @@ public:
*/
mutable_buffers_type prepare(std::size_t n)
{
if (size () > max_size() || max_size() - size() < n)
if (size() > max_size() || max_size() - size() < n)
{
std::length_error ex("dynamic_string_buffer too long");
asio::detail::throw_exception(ex);
}
if (size_ == (std::numeric_limits<std::size_t>::max)())
size_ = string_.size(); // Enable v1 behaviour.
string_.resize(size_ + n);
return asio::buffer(asio::buffer(string_) + size_, n);
}
/// Move bytes from the output sequence to the input sequence.
/// @b DynamicBuffer_v1: Move bytes from the output sequence to the input
/// sequence.
/**
* @param n The number of bytes to append from the start of the output
* sequence to the end of the input sequence. The remainder of the output
@@ -1655,24 +1743,69 @@ public:
size_ += (std::min)(n, string_.size() - size_);
string_.resize(size_);
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Remove characters from the input sequence.
/// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of
/// bytes.
/**
* Removes @c n characters from the beginning of the input sequence.
* Resizes the string to accommodate an additional @c n bytes at the end.
*
* @note If @c n is greater than the size of the input sequence, the entire
* input sequence is consumed and no error is issued.
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
*/
void grow(std::size_t n)
{
if (size() > max_size() || max_size() - size() < n)
{
std::length_error ex("dynamic_string_buffer too long");
asio::detail::throw_exception(ex);
}
string_.resize(size() + n);
}
/// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number
/// of bytes.
/**
* Erases @c n bytes from the end of the string by resizing the basic_string
* object. If @c n is greater than the current size of the string, the string
* is emptied.
*/
void shrink(std::size_t n)
{
string_.resize(n > size() ? 0 : size() - n);
}
/// @b DynamicBuffer_v1: Remove characters from the input sequence.
/// @b DynamicBuffer_v2: Consume the specified number of bytes from the
/// beginning of the underlying memory.
/**
* @b DynamicBuffer_v1: Removes @c n characters from the beginning of the
* input sequence. @note If @c n is greater than the size of the input
* sequence, the entire input sequence is consumed and no error is issued.
*
* @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the string.
* If @c n is greater than the current size of the string, the string is
* emptied.
*/
void consume(std::size_t n)
{
std::size_t consume_length = (std::min)(n, size_);
string_.erase(0, consume_length);
size_ -= consume_length;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
if (size_ != (std::numeric_limits<std::size_t>::max)())
{
std::size_t consume_length = (std::min)(n, size_);
string_.erase(0, consume_length);
size_ -= consume_length;
return;
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
string_.erase(0, n);
}
private:
std::basic_string<Elem, Traits, Allocator>& string_;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
std::size_t size_;
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
const std::size_t max_size_;
};
@@ -1684,19 +1817,20 @@ template <typename Elem, typename Allocator>
class dynamic_vector_buffer
{
public:
/// The type used to represent the input sequence as a list of buffers.
/// The type used to represent a sequence of constant buffers that refers to
/// the underlying memory.
typedef ASIO_CONST_BUFFER const_buffers_type;
/// The type used to represent the output sequence as a list of buffers.
/// The type used to represent a sequence of mutable buffers that refers to
/// the underlying memory.
typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
/// Construct a dynamic buffer from a string.
/// Construct a dynamic buffer from a vector.
/**
* @param v The vector to be used as backing storage for the dynamic buffer.
* Any existing data in the vector is treated as the dynamic buffer's input
* sequence. The object stores a reference to the vector and the user is
* responsible for ensuring that the vector object remains valid until the
* dynamic_vector_buffer object is destroyed.
* The object stores a reference to the vector and the user is responsible
* for ensuring that the vector object remains valid while the
* dynamic_vector_buffer object, and copies of the object, are in use.
*
* @param maximum_size Specifies a maximum size for the buffer, in bytes.
*/
@@ -1704,77 +1838,149 @@ public:
std::size_t maximum_size =
(std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
: vector_(v),
size_(vector_.size()),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_((std::numeric_limits<std::size_t>::max)()),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(maximum_size)
{
}
/// @b DynamicBuffer_v2: Copy construct a dynamic buffer.
dynamic_vector_buffer(const dynamic_vector_buffer& other) ASIO_NOEXCEPT
: vector_(other.vector_),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_(other.size_),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(other.max_size_)
{
}
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move construct a dynamic buffer.
dynamic_vector_buffer(dynamic_vector_buffer&& other) ASIO_NOEXCEPT
: vector_(other.vector_),
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
size_(other.size_),
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
max_size_(other.max_size_)
{
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Get the size of the input sequence.
/// @b DynamicBuffer_v1: Get the size of the input sequence.
/// @b DynamicBuffer_v2: Get the current size of the underlying memory.
/**
* @returns @b DynamicBuffer_v1 The current size of the input sequence.
* @b DynamicBuffer_v2: The current size of the underlying vector if less than
* max_size(). Otherwise returns max_size().
*/
std::size_t size() const ASIO_NOEXCEPT
{
return size_;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
if (size_ != (std::numeric_limits<std::size_t>::max)())
return size_;
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
return (std::min)(vector_.size(), max_size());
}
/// Get the maximum size of the dynamic buffer.
/**
* @returns The allowed maximum of the sum of the sizes of the input sequence
* and output sequence.
* @returns @b DynamicBuffer_v1: The allowed maximum of the sum of the sizes
* of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed
* maximum size of the underlying memory.
*/
std::size_t max_size() const ASIO_NOEXCEPT
{
return max_size_;
}
/// Get the current capacity of the dynamic buffer.
/// Get the maximum size that the buffer may grow to without triggering
/// reallocation.
/**
* @returns The current total capacity of the buffer, i.e. for both the input
* sequence and output sequence.
* @returns @b DynamicBuffer_v1: The current total capacity of the buffer,
* i.e. for both the input sequence and output sequence. @b DynamicBuffer_v2:
* The current capacity of the underlying vector if less than max_size().
* Otherwise returns max_size().
*/
std::size_t capacity() const ASIO_NOEXCEPT
{
return vector_.capacity();
return (std::min)(vector_.capacity(), max_size());
}
/// Get a list of buffers that represents the input sequence.
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// @b DynamicBuffer_v1: Get a list of buffers that represents the input
/// sequence.
/**
* @returns An object of type @c const_buffers_type that satisfies
* ConstBufferSequence requirements, representing the basic_string memory in
* ConstBufferSequence requirements, representing the vector memory in the
* input sequence.
*
* @note The returned object is invalidated by any @c dynamic_vector_buffer
* or @c basic_string member function that modifies the input sequence or
* output sequence.
* or @c vector member function that modifies the input sequence or output
* sequence.
*/
const_buffers_type data() const ASIO_NOEXCEPT
{
return const_buffers_type(asio::buffer(vector_, size_));
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Get a list of buffers that represents the output sequence, with the given
/// size.
/// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
/// underlying memory.
/**
* Ensures that the output sequence can accommodate @c n bytes, resizing the
* basic_string object as necessary.
* @param pos Position of the first byte to represent in the buffer sequence
*
* @param n The number of bytes to return in the buffer sequence. If the
* underlying memory is shorter, the buffer sequence represents as many bytes
* as are available.
*
* @returns An object of type @c mutable_buffers_type that satisfies
* MutableBufferSequence requirements, representing basic_string memory
* at the start of the output sequence of size @c n.
* MutableBufferSequence requirements, representing the vector memory.
*
* @note The returned object is invalidated by any @c dynamic_vector_buffer
* or @c vector member function that resizes or erases the vector.
*/
mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
{
return mutable_buffers_type(asio::buffer(
asio::buffer(vector_, max_size_) + pos, n));
}
/// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
/// underlying memory.
/**
* @param pos Position of the first byte to represent in the buffer sequence
*
* @param n The number of bytes to return in the buffer sequence. If the
* underlying memory is shorter, the buffer sequence represents as many bytes
* as are available.
*
* @note The returned object is invalidated by any @c dynamic_vector_buffer
* or @c vector member function that resizes or erases the vector.
*/
const_buffers_type data(std::size_t pos,
std::size_t n) const ASIO_NOEXCEPT
{
return const_buffers_type(asio::buffer(
asio::buffer(vector_, max_size_) + pos, n));
}
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// @b DynamicBuffer_v1: Get a list of buffers that represents the output
/// sequence, with the given size.
/**
* Ensures that the output sequence can accommodate @c n bytes, resizing the
* vector object as necessary.
*
* @returns An object of type @c mutable_buffers_type that satisfies
* MutableBufferSequence requirements, representing vector memory at the
* start of the output sequence of size @c n.
*
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
*
* @note The returned object is invalidated by any @c dynamic_vector_buffer
* or @c basic_string member function that modifies the input sequence or
* output sequence.
* or @c vector member function that modifies the input sequence or output
* sequence.
*/
mutable_buffers_type prepare(std::size_t n)
{
@@ -1784,12 +1990,16 @@ public:
asio::detail::throw_exception(ex);
}
if (size_ == (std::numeric_limits<std::size_t>::max)())
size_ = vector_.size(); // Enable v1 behaviour.
vector_.resize(size_ + n);
return asio::buffer(asio::buffer(vector_) + size_, n);
}
/// Move bytes from the output sequence to the input sequence.
/// @b DynamicBuffer_v1: Move bytes from the output sequence to the input
/// sequence.
/**
* @param n The number of bytes to append from the start of the output
* sequence to the end of the input sequence. The remainder of the output
@@ -1806,24 +2016,69 @@ public:
size_ += (std::min)(n, vector_.size() - size_);
vector_.resize(size_);
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Remove characters from the input sequence.
/// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of
/// bytes.
/**
* Removes @c n characters from the beginning of the input sequence.
* Resizes the vector to accommodate an additional @c n bytes at the end.
*
* @note If @c n is greater than the size of the input sequence, the entire
* input sequence is consumed and no error is issued.
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
*/
void grow(std::size_t n)
{
if (size() > max_size() || max_size() - size() < n)
{
std::length_error ex("dynamic_vector_buffer too long");
asio::detail::throw_exception(ex);
}
vector_.resize(size() + n);
}
/// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number
/// of bytes.
/**
* Erases @c n bytes from the end of the vector by resizing the vector
* object. If @c n is greater than the current size of the vector, the vector
* is emptied.
*/
void shrink(std::size_t n)
{
vector_.resize(n > size() ? 0 : size() - n);
}
/// @b DynamicBuffer_v1: Remove characters from the input sequence.
/// @b DynamicBuffer_v2: Consume the specified number of bytes from the
/// beginning of the underlying memory.
/**
* @b DynamicBuffer_v1: Removes @c n characters from the beginning of the
* input sequence. @note If @c n is greater than the size of the input
* sequence, the entire input sequence is consumed and no error is issued.
*
* @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the vector.
* If @c n is greater than the current size of the vector, the vector is
* emptied.
*/
void consume(std::size_t n)
{
std::size_t consume_length = (std::min)(n, size_);
vector_.erase(vector_.begin(), vector_.begin() + consume_length);
size_ -= consume_length;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
if (size_ != (std::numeric_limits<std::size_t>::max)())
{
std::size_t consume_length = (std::min)(n, size_);
vector_.erase(vector_.begin(), vector_.begin() + consume_length);
size_ -= consume_length;
return;
}
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n));
}
private:
std::vector<Elem, Allocator>& vector_;
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
std::size_t size_;
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
const std::size_t max_size_;
};
@@ -2157,6 +2412,83 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target,
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/detail/is_buffer_sequence.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
/// Trait to determine whether a type satisfies the MutableBufferSequence
/// requirements.
template <typename T>
struct is_mutable_buffer_sequence
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_buffer_sequence<T, mutable_buffer>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
/// Trait to determine whether a type satisfies the ConstBufferSequence
/// requirements.
template <typename T>
struct is_const_buffer_sequence
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_buffer_sequence<T, const_buffer>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Trait to determine whether a type satisfies the DynamicBuffer_v1
/// requirements.
template <typename T>
struct is_dynamic_buffer_v1
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_dynamic_buffer_v1<T>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
/// Trait to determine whether a type satisfies the DynamicBuffer_v2
/// requirements.
template <typename T>
struct is_dynamic_buffer_v2
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#else // defined(GENERATING_DOCUMENTATION)
: asio::detail::is_dynamic_buffer_v2<T>
#endif // defined(GENERATING_DOCUMENTATION)
{
};
/// Trait to determine whether a type satisfies the DynamicBuffer requirements.
/**
* If @c ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the
* type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c
* ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type
* satisfies the DynamicBuffer_v1 requirements.
*/
template <typename T>
struct is_dynamic_buffer
#if defined(GENERATING_DOCUMENTATION)
: integral_constant<bool, automatically_determined>
#elif defined(ASIO_NO_DYNAMIC_BUFFER_V1)
: asio::is_dynamic_buffer_v2<T>
#else // defined(ASIO_NO_DYNAMIC_BUFFER_V1)
: asio::is_dynamic_buffer_v1<T>
#endif // defined(ASIO_NO_DYNAMIC_BUFFER_V1)
{
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFER_HPP

View File

@@ -2,7 +2,7 @@
// buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -26,7 +26,6 @@
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#include "asio/detail/push_options.hpp"
@@ -105,22 +104,6 @@ public:
return next_layer_.lowest_layer().get_executor();
}
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return next_layer_.get_io_context();
}
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
{

View File

@@ -2,7 +2,7 @@
// buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -23,7 +23,6 @@
#include "asio/buffered_stream_fwd.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#include "asio/detail/push_options.hpp"
@@ -96,22 +95,6 @@ public:
return stream_impl_.lowest_layer().get_executor();
}
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return stream_impl_.get_io_context();
}
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return stream_impl_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
{

View File

@@ -2,7 +2,7 @@
// buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -25,7 +25,6 @@
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#include "asio/write.hpp"
#include "asio/detail/push_options.hpp"
@@ -105,22 +104,6 @@ public:
return next_layer_.lowest_layer().get_executor();
}
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_context()
{
return next_layer_.get_io_context();
}
/// (Deprecated: Use get_executor().) Get the io_context associated with the
/// object.
asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
#endif // !defined(ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
{

View File

@@ -2,7 +2,7 @@
// buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -0,0 +1,88 @@
//
// co_spawn.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_CO_SPAWN_HPP
#define ASIO_CO_SPAWN_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#include "asio/awaitable.hpp"
#include "asio/execution_context.hpp"
#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename T>
struct awaitable_signature;
template <typename T, typename Executor>
struct awaitable_signature<awaitable<T, Executor>>
{
typedef void type(std::exception_ptr, T);
};
template <typename Executor>
struct awaitable_signature<awaitable<void, Executor>>
{
typedef void type(std::exception_ptr);
};
} // namespace detail
/// Spawn a new thread of execution.
/**
* The entry point function object @c f must have the signature:
*
* @code awaitable<void, E> f(); @endcode
*
* where @c E is convertible from @c Executor.
*/
template <typename Executor, typename F, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(const Executor& ex, F&& f, CompletionToken&& token,
typename enable_if<
is_executor<Executor>::value
>::type* = 0);
/// Spawn a new thread of execution.
/**
* The entry point function object @c f must have the signature:
*
* @code awaitable<void, E> f(); @endcode
*
* where @c E is convertible from @c ExecutionContext::executor_type.
*/
template <typename ExecutionContext, typename F, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,
typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0);
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/impl/co_spawn.hpp"
#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#endif // ASIO_CO_SPAWN_HPP

View File

@@ -2,7 +2,7 @@
// completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -0,0 +1,136 @@
//
// compose.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_COMPOSE_HPP
#define ASIO_COMPOSE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/async_result.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|| defined(GENERATING_DOCUMENTATION)
/// Launch an asynchronous operation with a stateful implementation.
/**
* The async_compose function simplifies the implementation of composed
* asynchronous operations automatically wrapping a stateful function object
* with a conforming intermediate completion handler.
*
* @param implementation A function object that contains the implementation of
* the composed asynchronous operation. The first argument to the function
* object is a non-const reference to the enclosing intermediate completion
* handler. The remaining arguments are any arguments that originate from the
* completion handlers of any asynchronous operations performed by the
* implementation.
* @param token The completion token.
*
* @param io_objects_or_executors Zero or more I/O objects or I/O executors for
* which outstanding work must be maintained.
*
* @par Example:
*
* @code struct async_echo_implementation
* {
* tcp::socket& socket_;
* asio::mutable_buffer buffer_;
* enum { starting, reading, writing } state_;
*
* template <typename Self>
* void operator()(Self& self,
* asio::error_code error = {},
* std::size_t n = 0)
* {
* switch (state_)
* {
* case starting:
* state_ = reading;
* socket_.async_read_some(
* buffer_, std::move(self));
* break;
* case reading:
* if (error)
* {
* self.complete(error, 0);
* }
* else
* {
* state_ = writing;
* asio::async_write(socket_, buffer_,
* asio::transfer_exactly(n),
* std::move(self));
* }
* break;
* case writing:
* self.complete(error, n);
* break;
* }
* }
* };
*
* template <typename CompletionToken>
* auto async_echo(tcp::socket& socket,
* asio::mutable_buffer buffer,
* CompletionToken&& token) ->
* typename asio::async_result<
* typename std::decay<CompletionToken>::type,
* void(asio::error_code, std::size_t)>::return_type
* {
* return asio::async_compose<CompletionToken,
* void(asio::error_code, std::size_t)>(
* async_echo_implementation{socket, buffer,
* async_echo_implementation::starting},
* token, socket);
* } @endcode
*/
template <typename CompletionToken, typename Signature,
typename Implementation, typename... IoObjectsOrExecutors>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors);
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)
template <typename CompletionToken, typename Signature, typename Implementation>
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token);
#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
template <typename CompletionToken, typename Signature, \
typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \
ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \
async_compose(ASIO_MOVE_ARG(Implementation) implementation, \
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
ASIO_VARIADIC_MOVE_PARAMS(n));
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// || defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/impl/compose.hpp"
#endif // ASIO_COMPOSE_HPP

View File

@@ -2,7 +2,7 @@
// connect.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -58,7 +58,8 @@ struct is_endpoint_sequence
/**
* @defgroup connect asio::connect
*
* @brief Establishes a socket connection by trying each endpoint in a sequence.
* @brief The @c connect function is a composed operation that establishes a
* socket connection by trying each endpoint in a sequence.
*/
/*@{*/
@@ -81,14 +82,13 @@ struct is_endpoint_sequence
* Otherwise, contains the error from the last connection attempt.
*
* @par Example
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::connect(s, r.resolve(q)); @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
@@ -113,9 +113,9 @@ typename Protocol::endpoint connect(
* default-constructed endpoint.
*
* @par Example
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::error_code ec;
* asio::connect(s, r.resolve(q), ec);
* if (ec)
@@ -123,16 +123,15 @@ typename Protocol::endpoint connect(
* // An error occurred.
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, asio::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
/// sequence.
/// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c connect member
@@ -155,12 +154,12 @@ typename Protocol::endpoint connect(
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
/// sequence.
/// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c connect member
@@ -183,8 +182,8 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, asio::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -210,14 +209,14 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Otherwise, contains the error from the last connection attempt.
*
* @par Example
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::resolver::results_type e = r.resolve(q);
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::connect(s, e.begin(), e.end()); @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, Iterator end);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -242,10 +241,10 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* endpoint. Otherwise, the end iterator.
*
* @par Example
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::resolver::results_type e = r.resolve(q);
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::error_code ec;
* asio::connect(s, e.begin(), e.end(), ec);
* if (ec)
@@ -253,8 +252,8 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* // An error occurred.
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, Iterator end, asio::error_code& ec);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -301,17 +300,16 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* tcp::endpoint e = asio::connect(s,
* r.resolve(q), my_connect_condition());
* std::cout << "Connected to: " << e << std::endl; @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
@@ -361,9 +359,9 @@ typename Protocol::endpoint connect(
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::error_code ec;
* tcp::endpoint e = asio::connect(s,
* r.resolve(q), my_connect_condition(), ec);
@@ -376,18 +374,17 @@ typename Protocol::endpoint connect(
* std::cout << "Connected to: " << e << std::endl;
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
asio::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
/// sequence.
/// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c connect member
@@ -421,14 +418,14 @@ typename Protocol::endpoint connect(
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
/// sequence.
/// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c connect member
@@ -462,9 +459,9 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ConnectCondition connect_condition, asio::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -515,17 +512,17 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::resolver::results_type e = r.resolve(q);
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* tcp::resolver::results_type::iterator i = asio::connect(
* s, e.begin(), e.end(), my_connect_condition());
* std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
Iterator end, ConnectCondition connect_condition);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -575,10 +572,10 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::resolver::results_type e = r.resolve(q);
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::error_code ec;
* tcp::resolver::results_type::iterator i = asio::connect(
* s, e.begin(), e.end(), my_connect_condition());
@@ -591,9 +588,9 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* std::cout << "Connected to: " << i->endpoint() << std::endl;
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
asio::error_code& ec);
@@ -602,8 +599,8 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
/**
* @defgroup async_connect asio::async_connect
*
* @brief Asynchronously establishes a socket connection by trying each
* endpoint in a sequence.
* @brief The @c async_connect function is a composed asynchronous operation
* that establishes a socket connection by trying each endpoint in a sequence.
*/
/*@{*/
@@ -634,14 +631,14 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* const typename Protocol::endpoint& endpoint
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
*
* // ...
*
@@ -668,19 +665,19 @@ Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* // ...
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename EndpointSequence, typename RangeConnectHandler>
ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated.) Asynchronously establishes a socket connection by trying each
/// endpoint in a sequence.
/// (Deprecated: Use range overload.) Asynchronously establishes a socket
/// connection by trying each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c async_connect
@@ -706,20 +703,20 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Iterator iterator
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note This overload assumes that a default constructed object of type @c
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler,
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
#endif // !defined(ASIO_NO_DEPRECATED)
@@ -752,13 +749,13 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Iterator iterator
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* @code std::vector<tcp::endpoint> endpoints = ...;
* tcp::socket s(io_context);
* tcp::socket s(my_context);
* asio::async_connect(s,
* endpoints.begin(), endpoints.end(),
* connect_handler);
@@ -772,12 +769,11 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* // ...
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM,
template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end,
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
ASIO_MOVE_ARG(IteratorConnectHandler) handler);
/// Asynchronously establishes a socket connection by trying each endpoint in a
@@ -818,9 +814,9 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Iterator iterator
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* The following connect condition function object can be used to output
@@ -837,9 +833,9 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
*
* // ...
*
@@ -875,19 +871,19 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* }
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence,
template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0);
#if !defined(ASIO_NO_DEPRECATED)
/// (Deprecated.) Asynchronously establishes a socket connection by trying each
/// endpoint in a sequence.
/// (Deprecated: Use range overload.) Asynchronously establishes a socket
/// connection by trying each endpoint in a sequence.
/**
* This function attempts to connect a socket to one of a sequence of
* endpoints. It does this by repeated calls to the socket's @c async_connect
@@ -924,19 +920,19 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
* Iterator iterator
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @note This overload assumes that a default constructed object of type @c
* Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c asio::ip::tcp::resolver::iterator.
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ConnectCondition connect_condition,
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
@@ -982,9 +978,9 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* Iterator iterator
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_context::post().
* not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a
* manner equivalent to using asio::post().
*
* @par Example
* The following connect condition function object can be used to output
@@ -1001,9 +997,9 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* }
* }; @endcode
* It would be used with the asio::connect function as follows:
* @code tcp::resolver r(io_context);
* @code tcp::resolver r(my_context);
* tcp::resolver::query q("host", "service");
* tcp::socket s(io_context);
* tcp::socket s(my_context);
*
* // ...
*
@@ -1040,12 +1036,12 @@ async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
* }
* } @endcode
*/
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
Iterator end, ConnectCondition connect_condition,
ASIO_MOVE_ARG(IteratorConnectHandler) handler);
/*@}*/

View File

@@ -2,7 +2,7 @@
// coroutine.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -205,7 +205,7 @@ class coroutine_ref;
* {
* do
* {
* socket_.reset(new tcp::socket(io_context_));
* socket_.reset(new tcp::socket(my_context_));
* yield acceptor->async_accept(*socket_, *this);
* fork server(*this)();
* } while (is_parent());
@@ -227,7 +227,7 @@ class coroutine_ref;
* Note that @c fork doesn't do the actual forking by itself. It is the
* application's responsibility to create a clone of the coroutine and call it.
* The clone can be called immediately, as above, or scheduled for delayed
* execution using something like io_context::post().
* execution using something like asio::post().
*
* @par Alternate macro names
*

View File

@@ -1,466 +0,0 @@
//
// datagram_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#define ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
#include <cstddef>
#include "asio/async_result.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#if defined(ASIO_WINDOWS_RUNTIME)
# include "asio/detail/null_socket_service.hpp"
#elif defined(ASIO_HAS_IOCP)
# include "asio/detail/win_iocp_socket_service.hpp"
#else
# include "asio/detail/reactive_socket_service.hpp"
#endif
#include "asio/detail/push_options.hpp"
namespace asio {
/// Default service implementation for a datagram socket.
template <typename Protocol>
class datagram_socket_service
#if defined(GENERATING_DOCUMENTATION)
: public asio::io_context::service
#else
: public asio::detail::service_base<datagram_socket_service<Protocol> >
#endif
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
static asio::io_context::id id;
#endif
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
private:
// The type of the platform-specific implementation.
#if defined(ASIO_WINDOWS_RUNTIME)
typedef detail::null_socket_service<Protocol> service_impl_type;
#elif defined(ASIO_HAS_IOCP)
typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
#else
typedef detail::reactive_socket_service<Protocol> service_impl_type;
#endif
public:
/// The type of a datagram socket.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined implementation_type;
#else
typedef typename service_impl_type::implementation_type implementation_type;
#endif
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
/// Construct a new datagram socket service for the specified io_context.
explicit datagram_socket_service(asio::io_context& io_context)
: asio::detail::service_base<
datagram_socket_service<Protocol> >(io_context),
service_impl_(io_context)
{
}
/// Construct a new datagram socket implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
}
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a new datagram socket implementation.
void move_construct(implementation_type& impl,
implementation_type& other_impl)
{
service_impl_.move_construct(impl, other_impl);
}
/// Move-assign from another datagram socket implementation.
void move_assign(implementation_type& impl,
datagram_socket_service& other_service,
implementation_type& other_impl)
{
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
// All socket services have access to each other's implementations.
template <typename Protocol1> friend class datagram_socket_service;
/// Move-construct a new datagram socket implementation from another protocol
/// type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
datagram_socket_service<Protocol1>& other_service,
typename datagram_socket_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
impl, other_service.service_impl_, other_impl);
}
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroy a datagram socket implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
}
// Open a new datagram socket implementation.
ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, asio::error_code& ec)
{
if (protocol.type() == ASIO_OS_DEF(SOCK_DGRAM))
service_impl_.open(impl, protocol, ec);
else
ec = asio::error::invalid_argument;
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to a datagram socket.
ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
asio::error_code& ec)
{
service_impl_.assign(impl, protocol, native_socket, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
bool is_open(const implementation_type& impl) const
{
return service_impl_.is_open(impl);
}
/// Close a datagram socket implementation.
ASIO_SYNC_OP_VOID close(implementation_type& impl,
asio::error_code& ec)
{
service_impl_.close(impl, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Release ownership of the underlying socket.
native_handle_type release(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.release(impl, ec);
}
/// Get the native socket implementation.
native_handle_type native_handle(implementation_type& impl)
{
return service_impl_.native_handle(impl);
}
/// Cancel all asynchronous operations associated with the socket.
ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
asio::error_code& ec)
{
service_impl_.cancel(impl, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
bool at_mark(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.at_mark(impl, ec);
}
/// Determine the number of bytes available for reading.
std::size_t available(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.available(impl, ec);
}
// Bind the datagram socket to the specified local endpoint.
ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, asio::error_code& ec)
{
service_impl_.bind(impl, endpoint, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the datagram socket to the specified endpoint.
ASIO_SYNC_OP_VOID connect(implementation_type& impl,
const endpoint_type& peer_endpoint, asio::error_code& ec)
{
service_impl_.connect(impl, peer_endpoint, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
template <typename ConnectHandler>
ASIO_INITFN_RESULT_TYPE(ConnectHandler,
void (asio::error_code))
async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint,
ASIO_MOVE_ARG(ConnectHandler) handler)
{
async_completion<ConnectHandler,
void (asio::error_code)> init(handler);
service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
return init.result.get();
}
/// Set a socket option.
template <typename SettableSocketOption>
ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, asio::error_code& ec)
{
service_impl_.set_option(impl, option, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, asio::error_code& ec) const
{
service_impl_.get_option(impl, option, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, asio::error_code& ec)
{
service_impl_.io_control(impl, command, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
bool non_blocking(const implementation_type& impl) const
{
return service_impl_.non_blocking(impl);
}
/// Sets the non-blocking mode of the socket.
ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, asio::error_code& ec)
{
service_impl_.non_blocking(impl, mode, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
bool native_non_blocking(const implementation_type& impl) const
{
return service_impl_.native_non_blocking(impl);
}
/// Sets the non-blocking mode of the native socket implementation.
ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, asio::error_code& ec)
{
service_impl_.native_non_blocking(impl, mode, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
endpoint_type local_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.local_endpoint(impl, ec);
}
/// Get the remote endpoint.
endpoint_type remote_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.remote_endpoint(impl, ec);
}
/// Disable sends or receives on the socket.
ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
socket_base::shutdown_type what, asio::error_code& ec)
{
service_impl_.shutdown(impl, what, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Wait for the socket to become ready to read, ready to write, or to have
/// pending error conditions.
ASIO_SYNC_OP_VOID wait(implementation_type& impl,
socket_base::wait_type w, asio::error_code& ec)
{
service_impl_.wait(impl, w, ec);
ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Asynchronously wait for the socket to become ready to read, ready to
/// write, or to have pending error conditions.
template <typename WaitHandler>
ASIO_INITFN_RESULT_TYPE(WaitHandler,
void (asio::error_code))
async_wait(implementation_type& impl, socket_base::wait_type w,
ASIO_MOVE_ARG(WaitHandler) handler)
{
async_completion<WaitHandler,
void (asio::error_code)> init(handler);
service_impl_.async_wait(impl, w, init.completion_handler);
return init.result.get();
}
/// Send the given data to the peer.
template <typename ConstBufferSequence>
std::size_t send(implementation_type& impl,
const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.send(impl, buffers, flags, ec);
}
/// Start an asynchronous send.
template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_send(implementation_type& impl, const ConstBufferSequence& buffers,
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
service_impl_.async_send(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
/// Send a datagram to the specified endpoint.
template <typename ConstBufferSequence>
std::size_t send_to(implementation_type& impl,
const ConstBufferSequence& buffers, const endpoint_type& destination,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.send_to(impl, buffers, destination, flags, ec);
}
/// Start an asynchronous send.
template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_send_to(implementation_type& impl,
const ConstBufferSequence& buffers, const endpoint_type& destination,
socket_base::message_flags flags,
ASIO_MOVE_ARG(WriteHandler) handler)
{
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
service_impl_.async_send_to(impl, buffers,
destination, flags, init.completion_handler);
return init.result.get();
}
/// Receive some data from the peer.
template <typename MutableBufferSequence>
std::size_t receive(implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.receive(impl, buffers, flags, ec);
}
/// Start an asynchronous receive.
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_receive(implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
service_impl_.async_receive(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
/// Receive a datagram with the endpoint of the sender.
template <typename MutableBufferSequence>
std::size_t receive_from(implementation_type& impl,
const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
ec);
}
/// Start an asynchronous receive that will get the endpoint of the sender.
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_receive_from(implementation_type& impl,
const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags,
ASIO_MOVE_ARG(ReadHandler) handler)
{
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
service_impl_.async_receive_from(impl, buffers,
sender_endpoint, flags, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
void shutdown()
{
service_impl_.shutdown();
}
// The platform-specific implementation.
service_impl_type service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP

View File

@@ -2,7 +2,7 @@
// deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,173 +0,0 @@
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DEADLINE_TIMER_SERVICE_HPP
#define ASIO_DEADLINE_TIMER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_ENABLE_OLD_SERVICES)
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include "asio/async_result.hpp"
#include "asio/detail/deadline_timer_service.hpp"
#include "asio/io_context.hpp"
#include "asio/time_traits.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
/// Default service implementation for a timer.
template <typename TimeType,
typename TimeTraits = asio::time_traits<TimeType> >
class deadline_timer_service
#if defined(GENERATING_DOCUMENTATION)
: public asio::io_context::service
#else
: public asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >
#endif
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
static asio::io_context::id id;
#endif
/// The time traits type.
typedef TimeTraits traits_type;
/// The time type.
typedef typename traits_type::time_type time_type;
/// The duration type.
typedef typename traits_type::duration_type duration_type;
private:
// The type of the platform-specific implementation.
typedef detail::deadline_timer_service<traits_type> service_impl_type;
public:
/// The implementation type of the deadline timer.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined implementation_type;
#else
typedef typename service_impl_type::implementation_type implementation_type;
#endif
/// Construct a new timer service for the specified io_context.
explicit deadline_timer_service(asio::io_context& io_context)
: asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >(io_context),
service_impl_(io_context)
{
}
/// Construct a new timer implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
}
/// Destroy a timer implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
}
/// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, asio::error_code& ec)
{
return service_impl_.cancel(impl, ec);
}
/// Cancels one asynchronous wait operation associated with the timer.
std::size_t cancel_one(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.cancel_one(impl, ec);
}
/// Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
return service_impl_.expiry(impl);
}
/// Set the expiry time for the timer as an absolute time.
std::size_t expires_at(implementation_type& impl,
const time_type& expiry_time, asio::error_code& ec)
{
return service_impl_.expires_at(impl, expiry_time, ec);
}
/// Get the expiry time for the timer relative to now.
duration_type expires_from_now(const implementation_type& impl) const
{
return TimeTraits::subtract(service_impl_.expiry(impl), TimeTraits::now());
}
/// Set the expiry time for the timer relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration_type& expiry_time, asio::error_code& ec)
{
return service_impl_.expires_after(impl, expiry_time, ec);
}
// Perform a blocking wait on the timer.
void wait(implementation_type& impl, asio::error_code& ec)
{
service_impl_.wait(impl, ec);
}
// Start an asynchronous wait on the timer.
template <typename WaitHandler>
ASIO_INITFN_RESULT_TYPE(WaitHandler,
void (asio::error_code))
async_wait(implementation_type& impl,
ASIO_MOVE_ARG(WaitHandler) handler)
{
async_completion<WaitHandler,
void (asio::error_code)> init(handler);
service_impl_.async_wait(impl, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
void shutdown()
{
service_impl_.shutdown();
}
// The platform-specific implementation.
service_impl_type service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
// || defined(GENERATING_DOCUMENTATION)
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP

View File

@@ -2,7 +2,7 @@
// defer.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -31,6 +31,11 @@ namespace asio {
* executor. The function object is queued for execution, and is never called
* from the current thread prior to returning from <tt>defer()</tt>.
*
* The use of @c defer(), rather than @ref post(), indicates the caller's
* preference that the executor defer the queueing of the function object. This
* may allow the executor to optimise queueing for cases when the function
* object represents a continuation of the current call context.
*
* This function has the following effects:
*
* @li Constructs a function object handler of type @c Handler, initialized
@@ -59,6 +64,11 @@ ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
* The function object is queued for execution, and is never called from the
* current thread prior to returning from <tt>defer()</tt>.
*
* The use of @c defer(), rather than @ref post(), indicates the caller's
* preference that the executor defer the queueing of the function object. This
* may allow the executor to optimise queueing for cases when the function
* object represents a continuation of the current call context.
*
* This function has the following effects:
*
* @li Constructs a function object handler of type @c Handler, initialized

View File

@@ -0,0 +1,62 @@
//
// detached.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETACHED_HPP
#define ASIO_DETACHED_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include <memory>
#include "asio/detail/push_options.hpp"
namespace asio {
/// Class used to specify that an asynchronous operation is detached.
/**
* The detached_t class is used to indicate that an asynchronous operation is
* detached. That is, there is no completion handler waiting for the
* operation's result. A detached_t object may be passed as a handler to an
* asynchronous operation, typically using the special value
* @c asio::detached. For example:
* @code my_socket.async_send(my_buffer, asio::detached);
* @endcode
*/
class detached_t
{
public:
/// Constructor.
ASIO_CONSTEXPR detached_t()
{
}
};
/// A special value, similar to std::nothrow.
/**
* See the documentation for asio::detached_t for a usage example.
*/
#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
constexpr detached_t detached;
#elif defined(ASIO_MSVC)
__declspec(selectany) detached_t detached;
#endif
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/impl/detached.hpp"
#endif // ASIO_DETACHED_HPP

View File

@@ -2,7 +2,7 @@
// detail/array.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/array_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/assert.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/atomic_count.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/base_from_completion_cond.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -27,8 +27,9 @@ template <typename CompletionCondition>
class base_from_completion_cond
{
protected:
explicit base_from_completion_cond(CompletionCondition completion_condition)
: completion_condition_(completion_condition)
explicit base_from_completion_cond(CompletionCondition& completion_condition)
: completion_condition_(
ASIO_MOVE_CAST(CompletionCondition)(completion_condition))
{
}

View File

@@ -2,7 +2,7 @@
// detail/bind_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/buffer_sequence_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/call_stack.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/chrono.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/chrono_time_traits.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/completion_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/concurrency_hint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/conditionally_enabled_event.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/conditionally_enabled_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/config.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +11,20 @@
#ifndef ASIO_DETAIL_CONFIG_HPP
#define ASIO_DETAIL_CONFIG_HPP
// boostify: non-boost code starts here
#if !defined(ASIO_STANDALONE)
# if !defined(ASIO_ENABLE_BOOST)
# if (__cplusplus >= 201103)
# define ASIO_STANDALONE 1
# elif defined(_MSC_VER) && defined(_MSVC_LANG)
# if (_MSC_VER >= 1900) && (_MSVC_LANG >= 201103)
# define ASIO_STANDALONE 1
# endif // (_MSC_VER >= 1900) && (_MSVC_LANG >= 201103)
# endif // defined(_MSC_VER) && defined(_MSVC_LANG)
# endif // !defined(ASIO_ENABLE_BOOST)
#endif // !defined(ASIO_STANDALONE)
// boostify: non-boost code ends here
#if defined(ASIO_STANDALONE)
# define ASIO_DISABLE_BOOST_ARRAY 1
# define ASIO_DISABLE_BOOST_ASSERT 1
@@ -69,7 +83,7 @@
|| (!defined(__MWERKS__) && !defined(__EDG_VERSION__)))
# define ASIO_MSVC _MSC_VER
# endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC)
#endif // defined(ASIO_MSVC)
#endif // !defined(ASIO_MSVC)
// Clang / libc++ detection.
#if defined(__clang__)
@@ -108,15 +122,26 @@
# define ASIO_HAS_MOVE 1
# endif // (_MSC_VER >= 1700)
# endif // defined(ASIO_MSVC)
# if defined(__INTEL_CXX11_MODE__)
# if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
# define BOOST_ASIO_HAS_MOVE 1
# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
# if defined(__ICL) && (__ICL >= 1500)
# define BOOST_ASIO_HAS_MOVE 1
# endif // defined(__ICL) && (__ICL >= 1500)
# endif // defined(__INTEL_CXX11_MODE__)
# endif // !defined(ASIO_DISABLE_MOVE)
#endif // !defined(ASIO_HAS_MOVE)
// If ASIO_MOVE_CAST isn't defined, and move support is available, define
// ASIO_MOVE_ARG and ASIO_MOVE_CAST to take advantage of rvalue
// references and perfect forwarding.
// * ASIO_MOVE_ARG,
// * ASIO_NONDEDUCED_MOVE_ARG, and
// * ASIO_MOVE_CAST
// to take advantage of rvalue references and perfect forwarding.
#if defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST)
# define ASIO_MOVE_ARG(type) type&&
# define ASIO_MOVE_ARG2(type1, type2) type1, type2&&
# define ASIO_NONDEDUCED_MOVE_ARG(type) type&
# define ASIO_MOVE_CAST(type) static_cast<type&&>
# define ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&>
#endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST)
@@ -142,6 +167,7 @@
# else
# define ASIO_MOVE_ARG(type) type
# endif
# define ASIO_NONDEDUCED_MOVE_ARG(type) const type&
# define ASIO_MOVE_CAST(type) static_cast<const type&>
# define ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&>
#endif // !defined(ASIO_MOVE_CAST)
@@ -226,7 +252,7 @@
// Support noexcept on compilers known to allow it.
#if !defined(ASIO_NOEXCEPT)
# if !defined(ASIO_DISABLE_NOEXCEPT)
# if (BOOST_VERSION >= 105300)
# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300)
# define ASIO_NOEXCEPT BOOST_NOEXCEPT
# define ASIO_NOEXCEPT_OR_NOTHROW BOOST_NOEXCEPT_OR_NOTHROW
# elif defined(__clang__)
@@ -272,9 +298,9 @@
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
# if defined(ASIO_MSVC)
# if (_MSC_VER >= 1700)
# if (_MSC_VER >= 1800)
# define ASIO_HAS_DECLTYPE 1
# endif // (_MSC_VER >= 1700)
# endif // (_MSC_VER >= 1800)
# endif // defined(ASIO_MSVC)
# endif // !defined(ASIO_DISABLE_DECLTYPE)
#endif // !defined(ASIO_HAS_DECLTYPE)
@@ -440,7 +466,13 @@
# if __has_include(<atomic>)
# define ASIO_HAS_STD_ATOMIC 1
# endif // __has_include(<atomic>)
# endif // (__cplusplus >= 201103)
# elif defined(__apple_build_version__) && defined(_LIBCPP_VERSION)
# if (__clang_major__ >= 10)
# if __has_include(<atomic>)
# define ASIO_HAS_STD_ATOMIC 1
# endif // __has_include(<atomic>)
# endif // (__clang_major__ >= 10)
# endif /// defined(__apple_build_version__) && defined(_LIBCPP_VERSION)
# endif // defined(__clang__)
# if defined(__GNUC__)
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
@@ -770,32 +802,77 @@
# endif // !defined(ASIO_DISABLE_STD_FUTURE)
#endif // !defined(ASIO_HAS_STD_FUTURE)
// Standard library support for experimental::string_view.
// Standard library support for std::string_view.
#if !defined(ASIO_HAS_STD_STRING_VIEW)
# if !defined(ASIO_DISABLE_STD_STRING_VIEW)
# if defined(__clang__)
# if (__cplusplus >= 201402)
# if __has_include(<experimental/string_view>)
# if defined(ASIO_HAS_CLANG_LIBCXX)
# if (__cplusplus >= 201402)
# if __has_include(<string_view>)
# define ASIO_HAS_STD_STRING_VIEW 1
# endif // __has_include(<string_view>)
# endif // (__cplusplus >= 201402)
# else // defined(ASIO_HAS_CLANG_LIBCXX)
# if (__cplusplus >= 201703)
# if __has_include(<string_view>)
# define ASIO_HAS_STD_STRING_VIEW 1
# endif // __has_include(<string_view>)
# endif // (__cplusplus >= 201703)
# endif // defined(ASIO_HAS_CLANG_LIBCXX)
# elif defined(__GNUC__)
# if (__GNUC__ >= 7)
# if (__cplusplus >= 201703)
# define ASIO_HAS_STD_STRING_VIEW 1
# define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
# endif // __has_include(<experimental/string_view>)
# endif // (__cplusplus >= 201402)
# endif // (__cplusplus >= 201703)
# endif // (__GNUC__ >= 7)
# elif defined(ASIO_MSVC)
# if (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)
# define ASIO_HAS_STD_STRING_VIEW 1
# endif // (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)
# endif // defined(ASIO_MSVC)
# endif // !defined(ASIO_DISABLE_STD_STRING_VIEW)
#endif // !defined(ASIO_HAS_STD_STRING_VIEW)
// Standard library support for std::experimental::string_view.
#if !defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
# if !defined(ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)
# if defined(__clang__)
# if defined(ASIO_HAS_CLANG_LIBCXX)
# if (_LIBCPP_VERSION < 7000)
# if (__cplusplus >= 201402)
# if __has_include(<experimental/string_view>)
# define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
# endif // __has_include(<experimental/string_view>)
# endif // (__cplusplus >= 201402)
# endif // (_LIBCPP_VERSION < 7000)
# else // defined(ASIO_HAS_CLANG_LIBCXX)
# if (__cplusplus >= 201402)
# if __has_include(<experimental/string_view>)
# define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
# endif // __has_include(<experimental/string_view>)
# endif // (__cplusplus >= 201402)
# endif // // defined(ASIO_HAS_CLANG_LIBCXX)
# endif // defined(__clang__)
# if defined(__GNUC__)
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)
# if (__cplusplus >= 201402)
# define ASIO_HAS_STD_STRING_VIEW 1
# define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
# endif // (__cplusplus >= 201402)
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
# if defined(ASIO_MSVC)
# if (_MSC_VER >= 1910 && _HAS_CXX17)
# define ASIO_HAS_STD_STRING_VIEW
# endif // (_MSC_VER >= 1910)
# endif // defined(ASIO_MSVC)
# endif // !defined(ASIO_DISABLE_STD_STRING_VIEW)
#endif // !defined(ASIO_HAS_STD_STRING_VIEW)
# endif // !defined(ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)
#endif // !defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
// Standard library has a string_view that we can use.
#if !defined(ASIO_HAS_STRING_VIEW)
# if !defined(ASIO_DISABLE_STRING_VIEW)
# if defined(ASIO_HAS_STD_STRING_VIEW)
# define ASIO_HAS_STRING_VIEW 1
# elif defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
# define ASIO_HAS_STRING_VIEW 1
# endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
# endif // !defined(ASIO_DISABLE_STRING_VIEW)
#endif // !defined(ASIO_HAS_STRING_VIEW)
// Standard library support for iostream move construction and assignment.
#if !defined(ASIO_HAS_STD_IOSTREAM_MOVE)
@@ -815,6 +892,17 @@
# endif // !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE)
#endif // !defined(ASIO_HAS_STD_IOSTREAM_MOVE)
// Standard library has invoke_result (which supersedes result_of).
#if !defined(ASIO_HAS_STD_INVOKE_RESULT)
# if !defined(ASIO_DISABLE_STD_INVOKE_RESULT)
# if defined(ASIO_MSVC)
# if (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)
# define ASIO_HAS_STD_INVOKE_RESULT 1
# endif // (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)
# endif // defined(ASIO_MSVC)
# endif // !defined(ASIO_DISABLE_STD_INVOKE_RESULT)
#endif // !defined(ASIO_HAS_STD_INVOKE_RESULT)
// Windows App target. Windows but with a limited API.
#if !defined(ASIO_WINDOWS_APP)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)
@@ -860,15 +948,15 @@
# if defined(_MSC_VER) || defined(__BORLANDC__)
# pragma message( \
"Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
"- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
"- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
"Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
"- add -D_WIN32_WINNT=0x0601 to the compiler command line; or\n"\
"- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.\n"\
"Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).")
# else // defined(_MSC_VER) || defined(__BORLANDC__)
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
# warning For example, add -D_WIN32_WINNT=0x0601 to the compiler command line.
# warning Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
# define _WIN32_WINNT 0x0501
# define _WIN32_WINNT 0x0601
# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
# if defined(_MSC_VER)
# if defined(_WIN32) && !defined(WIN32)
@@ -939,7 +1027,8 @@
|| defined(__FreeBSD__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__)
|| defined(__linux__) \
|| defined(__HAIKU__)
# define ASIO_HAS_UNISTD_H 1
# endif
# endif // !defined(ASIO_HAS_BOOST_CONFIG)
@@ -1303,33 +1392,6 @@
// || (defined(__MACH__) && defined(__APPLE__))
#endif // !defined(ASIO_DISABLE_SSIZE_T)
// Helper macros to manage the transition away from the old services-based API.
#if defined(ASIO_ENABLE_OLD_SERVICES)
# define ASIO_SVC_TPARAM , typename Service
# define ASIO_SVC_TPARAM_DEF1(d1) , typename Service d1
# define ASIO_SVC_TPARAM_DEF2(d1, d2) , typename Service d1, d2
# define ASIO_SVC_TARG , Service
# define ASIO_SVC_T Service
# define ASIO_SVC_TPARAM1 , typename Service1
# define ASIO_SVC_TPARAM1_DEF1(d1) , typename Service1 d1
# define ASIO_SVC_TPARAM1_DEF2(d1, d2) , typename Service1 d1, d2
# define ASIO_SVC_TARG1 , Service1
# define ASIO_SVC_T1 Service1
# define ASIO_SVC_ACCESS public
#else // defined(ASIO_ENABLE_OLD_SERVICES)
# define ASIO_SVC_TPARAM
# define ASIO_SVC_TPARAM_DEF1(d1)
# define ASIO_SVC_TPARAM_DEF2(d1, d2)
# define ASIO_SVC_TARG
// ASIO_SVC_T is defined at each point of use.
# define ASIO_SVC_TPARAM1
# define ASIO_SVC_TPARAM1_DEF1(d1)
# define ASIO_SVC_TPARAM1_DEF2(d1, d2)
# define ASIO_SVC_TARG1
// ASIO_SVC_T1 is defined at each point of use.
# define ASIO_SVC_ACCESS protected
#endif // defined(ASIO_ENABLE_OLD_SERVICES)
// Helper macros to manage transition away from error_code return values.
#if defined(ASIO_NO_DEPRECATED)
# define ASIO_SYNC_OP_VOID void
@@ -1369,4 +1431,24 @@
# define ASIO_UNUSED_VARIABLE
#endif // !defined(ASIO_UNUSED_VARIABLE)
// Support co_await on compilers known to allow it.
#if !defined(ASIO_HAS_CO_AWAIT)
# if !defined(ASIO_DISABLE_CO_AWAIT)
# if defined(ASIO_MSVC)
# if (_MSC_FULL_VER >= 190023506)
# if defined(_RESUMABLE_FUNCTIONS_SUPPORTED)
# define ASIO_HAS_CO_AWAIT 1
# endif // defined(_RESUMABLE_FUNCTIONS_SUPPORTED)
# endif // (_MSC_FULL_VER >= 190023506)
# endif // defined(ASIO_MSVC)
# endif // !defined(ASIO_DISABLE_CO_AWAIT)
# if defined(__clang__)
# if (__cpp_coroutines >= 201703)
# if __has_include(<experimental/coroutine>)
# define ASIO_HAS_CO_AWAIT 1
# endif // __has_include(<experimental/coroutine>)
# endif // (__cpp_coroutines >= 201703)
# endif // defined(__clang__)
#endif // !defined(ASIO_HAS_CO_AWAIT)
#endif // ASIO_DETAIL_CONFIG_HPP

View File

@@ -2,7 +2,7 @@
// detail/consuming_buffers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -101,7 +101,7 @@ public:
std::advance(next, next_elem_);
std::size_t elem_offset = next_elem_offset_;
while (next != end && max_size > 0 && result.count < result.max_buffers)
while (next != end && max_size > 0 && (result.count) < result.max_buffers)
{
Buffer next_buf = Buffer(*next) + elem_offset;
result.elems[result.count] = asio::buffer(next_buf, max_size);
@@ -400,7 +400,7 @@ public:
// No-op.
}
std::size_t total_consume() const
std::size_t total_consumed() const
{
return 0;
}

View File

@@ -2,7 +2,7 @@
// detail/cstddef.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/cstdint.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/date_time_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,7 +18,7 @@
#include "asio/detail/config.hpp"
#include <cstddef>
#include "asio/error.hpp"
#include "asio/io_context.hpp"
#include "asio/execution_context.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/memory.hpp"
@@ -43,7 +43,7 @@ namespace detail {
template <typename Time_Traits>
class deadline_timer_service
: public service_base<deadline_timer_service<Time_Traits> >
: public execution_context_service_base<deadline_timer_service<Time_Traits> >
{
public:
// The time type.
@@ -63,9 +63,10 @@ public:
};
// Constructor.
deadline_timer_service(asio::io_context& io_context)
: service_base<deadline_timer_service<Time_Traits> >(io_context),
scheduler_(asio::use_service<timer_scheduler>(io_context))
deadline_timer_service(execution_context& context)
: execution_context_service_base<
deadline_timer_service<Time_Traits> >(context),
scheduler_(asio::use_service<timer_scheduler>(context))
{
scheduler_.init_task();
scheduler_.add_timer_queue(timer_queue_);
@@ -225,14 +226,15 @@ public:
}
// Start an asynchronous wait on the timer.
template <typename Handler>
void async_wait(implementation_type& impl, Handler& handler)
template <typename Handler, typename IoExecutor>
void async_wait(implementation_type& impl,
Handler& handler, const IoExecutor& io_ex)
{
// Allocate and construct an operation to wrap the handler.
typedef wait_handler<Handler> op;
typedef wait_handler<Handler, IoExecutor> op;
typename op::ptr p = { asio::detail::addressof(handler),
op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
p.p = new (p.v) op(handler, io_ex);
impl.might_have_pending_waits = true;

View File

@@ -2,7 +2,7 @@
// detail/dependent_type.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/descriptor_ops.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/descriptor_read_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -66,20 +66,21 @@ private:
MutableBufferSequence buffers_;
};
template <typename MutableBufferSequence, typename Handler>
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
class descriptor_read_op
: public descriptor_read_op_base<MutableBufferSequence>
{
public:
ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
descriptor_read_op(int descriptor,
const MutableBufferSequence& buffers, Handler& handler)
descriptor_read_op(int descriptor, const MutableBufferSequence& buffers,
Handler& handler, const IoExecutor& io_ex)
: descriptor_read_op_base<MutableBufferSequence>(
descriptor, buffers, &descriptor_read_op::do_complete),
handler_(ASIO_MOVE_CAST(Handler)(handler))
handler_(ASIO_MOVE_CAST(Handler)(handler)),
io_executor_(io_ex)
{
handler_work<Handler>::start(handler_);
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
}
static void do_complete(void* owner, operation* base,
@@ -89,7 +90,7 @@ public:
// Take ownership of the handler object.
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
ptr p = { asio::detail::addressof(o->handler_), o, o };
handler_work<Handler> w(o->handler_);
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
ASIO_HANDLER_COMPLETION((*o));
@@ -116,6 +117,7 @@ public:
private:
Handler handler_;
IoExecutor io_executor_;
};
} // namespace detail

View File

@@ -2,7 +2,7 @@
// detail/descriptor_write_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -66,20 +66,21 @@ private:
ConstBufferSequence buffers_;
};
template <typename ConstBufferSequence, typename Handler>
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
class descriptor_write_op
: public descriptor_write_op_base<ConstBufferSequence>
{
public:
ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);
descriptor_write_op(int descriptor,
const ConstBufferSequence& buffers, Handler& handler)
descriptor_write_op(int descriptor, const ConstBufferSequence& buffers,
Handler& handler, const IoExecutor& io_ex)
: descriptor_write_op_base<ConstBufferSequence>(
descriptor, buffers, &descriptor_write_op::do_complete),
handler_(ASIO_MOVE_CAST(Handler)(handler))
handler_(ASIO_MOVE_CAST(Handler)(handler)),
io_executor_(io_ex)
{
handler_work<Handler>::start(handler_);
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
}
static void do_complete(void* owner, operation* base,
@@ -89,7 +90,7 @@ public:
// Take ownership of the handler object.
descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
ptr p = { asio::detail::addressof(o->handler_), o, o };
handler_work<Handler> w(o->handler_);
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
ASIO_HANDLER_COMPLETION((*o));
@@ -116,6 +117,7 @@ public:
private:
Handler handler_;
IoExecutor io_executor_;
};
} // namespace detail

View File

@@ -2,7 +2,7 @@
// detail/dev_poll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/epoll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -32,6 +32,10 @@
#include "asio/detail/wait_op.hpp"
#include "asio/execution_context.hpp"
#if defined(ASIO_HAS_TIMERFD)
# include <sys/timerfd.h>
#endif // defined(ASIO_HAS_TIMERFD)
#include "asio/detail/push_options.hpp"
namespace asio {

View File

@@ -2,7 +2,7 @@
// detail/event.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/eventfd_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying

View File

@@ -0,0 +1,104 @@
//
// detail/executor_function.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
#define ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
class executor_function_base
{
public:
void complete()
{
func_(this, true);
}
void destroy()
{
func_(this, false);
}
protected:
typedef void (*func_type)(executor_function_base*, bool);
executor_function_base(func_type func)
: func_(func)
{
}
// Prevents deletion through this type.
~executor_function_base()
{
}
private:
func_type func_;
};
template <typename Function, typename Alloc>
class executor_function : public executor_function_base
{
public:
ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
thread_info_base::executor_function_tag, executor_function);
template <typename F>
executor_function(ASIO_MOVE_ARG(F) f, const Alloc& allocator)
: executor_function_base(&executor_function::do_complete),
function_(ASIO_MOVE_CAST(F)(f)),
allocator_(allocator)
{
}
static void do_complete(executor_function_base* base, bool call)
{
// Take ownership of the function object.
executor_function* o(static_cast<executor_function*>(base));
Alloc allocator(o->allocator_);
ptr p = { detail::addressof(allocator), o, o };
// Make a copy of the function so that the memory can be deallocated before
// the upcall is made. Even if we're not about to make an upcall, a
// sub-object of the function may be the true owner of the memory
// associated with the function. Consequently, a local copy of the function
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Function function(ASIO_MOVE_CAST(Function)(o->function_));
p.reset();
// Make the upcall if required.
if (call)
{
function();
}
}
private:
Function function_;
Alloc allocator_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EXECUTOR_FUNCTION_HPP

View File

@@ -2,7 +2,7 @@
// detail/executor_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/functional.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -0,0 +1,33 @@
//
// detail/future.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_FUTURE_HPP
#define ASIO_DETAIL_FUTURE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_STD_FUTURE)
# include <future>
// Even though the future header is available, libstdc++ may not implement the
// std::future class itself. However, we need to have already included the
// future header to reliably test for _GLIBCXX_HAS_GTHREADS.
# if defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)
# if defined(_GLIBCXX_HAS_GTHREADS)
# define ASIO_HAS_STD_FUTURE_CLASS 1
# endif // defined(_GLIBCXX_HAS_GTHREADS)
# else // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)
# define ASIO_HAS_STD_FUTURE_CLASS 1
# endif // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)
#endif // defined(ASIO_HAS_STD_FUTURE)
#endif // ASIO_DETAIL_FUTURE_HPP

View File

@@ -2,7 +2,7 @@
// detail/gcc_arm_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/gcc_hppa_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/gcc_sync_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/gcc_x86_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/global.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/handler_alloc_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -192,7 +192,7 @@ struct get_hook_allocator<Handler, std::allocator<T> >
} \
/**/
#define ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
#define ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \
struct ptr \
{ \
const Alloc* a; \
@@ -205,9 +205,10 @@ struct get_hook_allocator<Handler, std::allocator<T> >
static op* allocate(const Alloc& a) \
{ \
typedef typename ::asio::detail::get_recycling_allocator< \
Alloc>::type recycling_allocator_type; \
Alloc, purpose>::type recycling_allocator_type; \
ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
::asio::detail::get_recycling_allocator<Alloc>::get(a)); \
::asio::detail::get_recycling_allocator< \
Alloc, purpose>::get(a)); \
return a1.allocate(1); \
} \
void reset() \
@@ -220,9 +221,10 @@ struct get_hook_allocator<Handler, std::allocator<T> >
if (v) \
{ \
typedef typename ::asio::detail::get_recycling_allocator< \
Alloc>::type recycling_allocator_type; \
Alloc, purpose>::type recycling_allocator_type; \
ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
::asio::detail::get_recycling_allocator<Alloc>::get(*a)); \
::asio::detail::get_recycling_allocator< \
Alloc, purpose>::get(*a)); \
a1.deallocate(static_cast<op*>(v), 1); \
v = 0; \
} \
@@ -230,6 +232,11 @@ struct get_hook_allocator<Handler, std::allocator<T> >
} \
/**/
#define ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \
::asio::detail::thread_info_base::default_tag, op ) \
/**/
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP

View File

@@ -2,7 +2,7 @@
// detail/handler_cont_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/handler_invoke_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/handler_tracking.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/handler_type_requirements.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -127,7 +127,7 @@ struct handler_type_requirements
{
};
#define ASIO_COMPLETION_HANDLER_CHECK( \
#define ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
handler_type, handler) \
\
typedef ASIO_HANDLER_TYPE(handler_type, \
@@ -492,7 +492,7 @@ struct handler_type_requirements
#else // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
#define ASIO_COMPLETION_HANDLER_CHECK( \
#define ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
handler_type, handler) \
typedef int ASIO_UNUSED_TYPEDEF

View File

@@ -2,7 +2,7 @@
// detail/handler_work.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -27,24 +27,41 @@ namespace detail {
// A helper class template to allow completion handlers to be dispatched
// through either the new executors framework or the old invocaton hook. The
// primary template uses the new executors framework.
template <typename Handler, typename Executor
= typename associated_executor<Handler>::type>
template <typename Handler,
typename IoExecutor = system_executor, typename HandlerExecutor
= typename associated_executor<Handler, IoExecutor>::type>
class handler_work
{
public:
explicit handler_work(Handler& handler) ASIO_NOEXCEPT
: executor_(associated_executor<Handler>::get(handler))
: io_executor_(),
executor_(asio::get_associated_executor(handler, io_executor_))
{
}
handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT
: io_executor_(io_ex),
executor_(asio::get_associated_executor(handler, io_executor_))
{
}
static void start(Handler& handler) ASIO_NOEXCEPT
{
Executor ex(associated_executor<Handler>::get(handler));
HandlerExecutor ex(asio::get_associated_executor(handler));
ex.on_work_started();
}
static void start(Handler& handler,
const IoExecutor& io_ex) ASIO_NOEXCEPT
{
HandlerExecutor ex(asio::get_associated_executor(handler, io_ex));
ex.on_work_started();
io_ex.on_work_started();
}
~handler_work()
{
io_executor_.on_work_finished();
executor_.on_work_finished();
}
@@ -52,7 +69,7 @@ public:
void complete(Function& function, Handler& handler)
{
executor_.dispatch(ASIO_MOVE_CAST(Function)(function),
associated_allocator<Handler>::get(handler));
asio::get_associated_allocator(handler));
}
private:
@@ -60,7 +77,8 @@ private:
handler_work(const handler_work&);
handler_work& operator=(const handler_work&);
typename associated_executor<Handler>::type executor_;
IoExecutor io_executor_;
HandlerExecutor executor_;
};
// This specialisation dispatches a handler through the old invocation hook.
@@ -68,7 +86,7 @@ private:
// system_executor will dispatch through the hook anyway. However, by doing
// this we avoid an extra copy of the handler.
template <typename Handler>
class handler_work<Handler, system_executor>
class handler_work<Handler, system_executor, system_executor>
{
public:
explicit handler_work(Handler&) ASIO_NOEXCEPT {}

View File

@@ -2,7 +2,7 @@
// detail/hash_map.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/impl/buffer_sequence_adapter.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -2,7 +2,7 @@
// detail/impl/descriptor_ops.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Some files were not shown because too many files have changed in this diff Show More