From 68a7cd26a6df6ae392dd65592ce784a06e4b6d44 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sun, 22 Sep 2013 22:13:33 +0000 Subject: [PATCH] Merge asio from trunk. ------------------------------------------------------------------------ r85735 | chris_kohlhoff | 2013-09-18 07:31:55 +1000 (Wed, 18 Sep 2013) | 1 line Remove dependency on Boost.Preprocessor library. ------------------------------------------------------------------------ r85736 | chris_kohlhoff | 2013-09-18 07:32:48 +1000 (Wed, 18 Sep 2013) | 1 line Fix error in async_receive_from example. ------------------------------------------------------------------------ r85737 | chris_kohlhoff | 2013-09-18 07:33:39 +1000 (Wed, 18 Sep 2013) | 1 line Remove unused variable assignment. ------------------------------------------------------------------------ r85738 | chris_kohlhoff | 2013-09-18 07:35:43 +1000 (Wed, 18 Sep 2013) | 3 lines Fix a regression where, on some platforms, errors from async_connect are not correctly propagated through to the completion handler. ------------------------------------------------------------------------ r85739 | chris_kohlhoff | 2013-09-18 07:36:54 +1000 (Wed, 18 Sep 2013) | 1 line Remove unused parameters and member variables. ------------------------------------------------------------------------ r85740 | chris_kohlhoff | 2013-09-18 07:38:41 +1000 (Wed, 18 Sep 2013) | 1 line Fix nfds argument to select. ------------------------------------------------------------------------ r85741 | chris_kohlhoff | 2013-09-18 07:39:38 +1000 (Wed, 18 Sep 2013) | 1 line Fix a regression on Windows where multiple threads are running an io_service. ------------------------------------------------------------------------ r85742 | chris_kohlhoff | 2013-09-18 07:40:19 +1000 (Wed, 18 Sep 2013) | 1 line Fix typo in serial ports overview. ------------------------------------------------------------------------ r85743 | chris_kohlhoff | 2013-09-18 07:41:04 +1000 (Wed, 18 Sep 2013) | 1 line Ensure ssl::io_op::want_ member is initialised. ------------------------------------------------------------------------ r85744 | chris_kohlhoff | 2013-09-18 07:42:08 +1000 (Wed, 18 Sep 2013) | 1 line Fix a bug in handler tracking, where it was not correctly printing out some handler IDs. ------------------------------------------------------------------------ r85745 | chris_kohlhoff | 2013-09-18 07:42:48 +1000 (Wed, 18 Sep 2013) | 1 line Fix comparison used to test for a successful synchronous accept. ------------------------------------------------------------------------ r85746 | chris_kohlhoff | 2013-09-18 07:43:29 +1000 (Wed, 18 Sep 2013) | 3 lines Ensure signal number is correctly passed to the completion handler when starting an async_wait on a signal that is already raised. ------------------------------------------------------------------------ r85747 | chris_kohlhoff | 2013-09-18 07:45:43 +1000 (Wed, 18 Sep 2013) | 1 line Suppress g++ 4.8+ warning about unused typedefs. ------------------------------------------------------------------------ r85748 | chris_kohlhoff | 2013-09-18 07:48:54 +1000 (Wed, 18 Sep 2013) | 1 line Fix link to refer to native_handle() rather than the deprecated native() function. ------------------------------------------------------------------------ r85749 | chris_kohlhoff | 2013-09-18 07:51:28 +1000 (Wed, 18 Sep 2013) | 3 lines Enable the move optimisation (and otherwise eliminate a copy) for handlers using the default invocation hook. ------------------------------------------------------------------------ r85750 | chris_kohlhoff | 2013-09-18 07:52:27 +1000 (Wed, 18 Sep 2013) | 2 lines Clarify that programs must not issue overlapping async_write_at operations. ------------------------------------------------------------------------ r85751 | chris_kohlhoff | 2013-09-18 07:53:03 +1000 (Wed, 18 Sep 2013) | 1 line Fix error in comment. ------------------------------------------------------------------------ r85752 | chris_kohlhoff | 2013-09-18 07:53:45 +1000 (Wed, 18 Sep 2013) | 1 line Remove spurious whitespace. ------------------------------------------------------------------------ r85753 | chris_kohlhoff | 2013-09-18 08:00:53 +1000 (Wed, 18 Sep 2013) | 2 lines Clean up some internal forward declarations. ------------------------------------------------------------------------ r85754 | chris_kohlhoff | 2013-09-18 08:01:26 +1000 (Wed, 18 Sep 2013) | 1 line Add missing move cast. ------------------------------------------------------------------------ r85755 | chris_kohlhoff | 2013-09-18 08:03:29 +1000 (Wed, 18 Sep 2013) | 3 lines Fix another socket descriptor comparison that doesn't work correctly if the descriptor type is unsigned. ------------------------------------------------------------------------ r85756 | chris_kohlhoff | 2013-09-18 08:04:10 +1000 (Wed, 18 Sep 2013) | 3 lines Fix documentation error where an asynchronous function was described as having synchronous behaviour. ------------------------------------------------------------------------ r85757 | chris_kohlhoff | 2013-09-18 08:04:55 +1000 (Wed, 18 Sep 2013) | 1 line Add missing forward declarations needed for Windows. ------------------------------------------------------------------------ r85758 | chris_kohlhoff | 2013-09-18 08:05:38 +1000 (Wed, 18 Sep 2013) | 1 line Remove use of std::min. ------------------------------------------------------------------------ r85759 | chris_kohlhoff | 2013-09-18 08:06:25 +1000 (Wed, 18 Sep 2013) | 3 lines Inore ERROR_MORE_DATA as a non-fatal error when returned by GetOverlappedResult for a synchronous read. ------------------------------------------------------------------------ r85760 | chris_kohlhoff | 2013-09-18 08:08:07 +1000 (Wed, 18 Sep 2013) | 2 lines Enable certain C++11 standard library facilities for recent versions of Microsoft Visual Studio. ------------------------------------------------------------------------ r85761 | chris_kohlhoff | 2013-09-18 08:08:43 +1000 (Wed, 18 Sep 2013) | 4 lines Visual C++ language extensions use generic as a keyword. Add a workaround that renames the namespace to cpp_generic when those language extensions are in effect. ------------------------------------------------------------------------ r85762 | chris_kohlhoff | 2013-09-18 08:12:07 +1000 (Wed, 18 Sep 2013) | 2 lines Some async operations that missed getting the async_result treatment. ------------------------------------------------------------------------ r85763 | chris_kohlhoff | 2013-09-18 08:14:14 +1000 (Wed, 18 Sep 2013) | 2 lines Eliminate some unnecessary handler copies. ------------------------------------------------------------------------ r85764 | chris_kohlhoff | 2013-09-18 08:24:19 +1000 (Wed, 18 Sep 2013) | 26 lines Initial port to Windows Runtime. This change adds limited support for using Asio with the Windows Runtime. It requires that the language extensions be enabled. Due to the restricted facilities exposed by the Windows Runtime API, the port comes with the following caveats: * The core facilities such as the io_service, strand, buffers, composed operations, timers, etc., should all work as normal. * For sockets, only client-side TCP is supported. * Explicit binding of a client-side TCP socket is not supported. * The cancel() function is not supported for sockets. Asynchronous operations may only be cancelled by closing the socket. * Operations that use null_buffers are not supported. * Only tcp::no_delay and socket_base::keep_alive options are supported. * Resolvers do not support service names, only numbers. I.e. you must use 80 rather than http. * Most resolver query flags have no effect. ------------------------------------------------------------------------ r85765 | chris_kohlhoff | 2013-09-18 08:32:13 +1000 (Wed, 18 Sep 2013) | 1 line Regenerate documentation. ------------------------------------------------------------------------ r85766 | chris_kohlhoff | 2013-09-18 08:38:04 +1000 (Wed, 18 Sep 2013) | 2 lines Enable move support for Microsoft Visual C++ 2012. ------------------------------------------------------------------------ r85767 | chris_kohlhoff | 2013-09-18 08:42:50 +1000 (Wed, 18 Sep 2013) | 2 lines Add use_future support for Microsoft Visual C++. ------------------------------------------------------------------------ r85768 | chris_kohlhoff | 2013-09-18 08:53:17 +1000 (Wed, 18 Sep 2013) | 2 lines Fix prefix on extern "C" function name. ------------------------------------------------------------------------ r85781 | chris_kohlhoff | 2013-09-19 08:43:01 +1000 (Thu, 19 Sep 2013) | 1 line Implement end-of-file condition for WinRT stream sockets. ------------------------------------------------------------------------ r85798 | chris_kohlhoff | 2013-09-20 22:00:44 +1000 (Fri, 20 Sep 2013) | 2 lines Update buffered stream operations to adhere to current handler patterns. ------------------------------------------------------------------------ r85799 | chris_kohlhoff | 2013-09-20 22:02:33 +1000 (Fri, 20 Sep 2013) | 1 line MinGW fix. ------------------------------------------------------------------------ r85800 | chris_kohlhoff | 2013-09-20 22:04:00 +1000 (Fri, 20 Sep 2013) | 1 line Change unit tests so that they don't depend on Boost.Thread. ------------------------------------------------------------------------ r85801 | chris_kohlhoff | 2013-09-20 22:10:45 +1000 (Fri, 20 Sep 2013) | 1 line Regenerate documentation. ------------------------------------------------------------------------ r85823 | danieljames | 2013-09-22 20:32:36 +1000 (Sun, 22 Sep 2013) | 1 line Fix copying C++11 allocation examples ------------------------------------------------------------------------ [SVN r85838] --- doc/Jamfile.v2 | 2 +- doc/overview/posix.qbk | 2 +- doc/overview/serial_ports.qbk | 2 +- doc/reference.dox | 1 + doc/reference.qbk | 139 +++- include/boost/asio/basic_datagram_socket.hpp | 7 +- include/boost/asio/basic_socket_iostream.hpp | 33 +- include/boost/asio/basic_socket_streambuf.hpp | 22 +- include/boost/asio/buffered_read_stream.hpp | 191 +----- include/boost/asio/buffered_stream.hpp | 32 +- include/boost/asio/buffered_write_stream.hpp | 170 +---- .../boost/asio/datagram_socket_service.hpp | 10 +- .../asio/detail/buffer_sequence_adapter.hpp | 28 +- include/boost/asio/detail/config.hpp | 172 ++++- .../asio/detail/deadline_timer_service.hpp | 12 + include/boost/asio/detail/descriptor_ops.hpp | 8 +- .../boost/asio/detail/dev_poll_reactor.hpp | 2 - .../asio/detail/dev_poll_reactor_fwd.hpp | 34 - include/boost/asio/detail/epoll_reactor.hpp | 2 - .../boost/asio/detail/epoll_reactor_fwd.hpp | 34 - include/boost/asio/detail/event.hpp | 6 +- include/boost/asio/detail/fd_set_adapter.hpp | 5 + .../asio/detail/handler_type_requirements.hpp | 58 +- .../detail/impl/buffer_sequence_adapter.ipp | 120 ++++ .../boost/asio/detail/impl/descriptor_ops.ipp | 8 +- .../asio/detail/impl/handler_tracking.ipp | 4 +- .../detail/impl/pipe_select_interrupter.ipp | 2 + .../impl/reactive_descriptor_service.ipp | 8 +- .../impl/reactive_socket_service_base.ipp | 4 +- .../boost/asio/detail/impl/select_reactor.hpp | 6 +- .../boost/asio/detail/impl/select_reactor.ipp | 4 +- .../asio/detail/impl/signal_set_service.ipp | 89 ++- include/boost/asio/detail/impl/socket_ops.ipp | 427 ++++++++++-- .../detail/impl/socket_select_interrupter.ipp | 4 + .../detail/impl/win_iocp_handle_service.ipp | 17 +- .../asio/detail/impl/win_iocp_io_service.ipp | 6 +- .../impl/winrt_ssocket_service_base.ipp | 614 ++++++++++++++++++ .../detail/impl/winrt_timer_scheduler.hpp | 81 +++ .../detail/impl/winrt_timer_scheduler.ipp | 124 ++++ include/boost/asio/detail/io_control.hpp | 4 +- include/boost/asio/detail/keyword_tss_ptr.hpp | 4 +- include/boost/asio/detail/kqueue_reactor.hpp | 2 - .../boost/asio/detail/kqueue_reactor_fwd.hpp | 35 - include/boost/asio/detail/mutex.hpp | 6 +- include/boost/asio/detail/null_reactor.hpp | 69 ++ .../boost/asio/detail/null_signal_blocker.hpp | 2 + .../boost/asio/detail/null_socket_service.hpp | 499 ++++++++++++++ .../asio/detail/pipe_select_interrupter.hpp | 2 + include/boost/asio/detail/pop_options.hpp | 7 + .../asio/detail/posix_fd_set_adapter.hpp | 8 +- include/boost/asio/detail/posix_tss_ptr.hpp | 1 - include/boost/asio/detail/push_options.hpp | 11 + .../detail/reactive_descriptor_service.hpp | 8 +- .../asio/detail/reactive_socket_accept_op.hpp | 2 +- .../detail/reactive_socket_connect_op.hpp | 21 +- .../asio/detail/reactive_socket_service.hpp | 4 +- .../detail/reactive_socket_service_base.hpp | 16 +- include/boost/asio/detail/reactor.hpp | 2 + include/boost/asio/detail/reactor_fwd.hpp | 26 +- .../boost/asio/detail/resolver_service.hpp | 5 + .../asio/detail/resolver_service_base.hpp | 2 + .../boost/asio/detail/select_interrupter.hpp | 4 + include/boost/asio/detail/select_reactor.hpp | 8 +- .../boost/asio/detail/select_reactor_fwd.hpp | 28 - .../asio/detail/service_registry_fwd.hpp | 28 - include/boost/asio/detail/signal_blocker.hpp | 2 + .../boost/asio/detail/signal_set_service.hpp | 10 +- include/boost/asio/detail/socket_ops.hpp | 9 +- include/boost/asio/detail/socket_option.hpp | 6 +- .../asio/detail/socket_select_interrupter.hpp | 4 + include/boost/asio/detail/socket_types.hpp | 254 +++++++- include/boost/asio/detail/static_mutex.hpp | 5 + include/boost/asio/detail/std_event.hpp | 129 ++++ include/boost/asio/detail/std_mutex.hpp | 75 +++ .../boost/asio/detail/std_static_mutex.hpp | 83 +++ include/boost/asio/detail/std_thread.hpp | 67 ++ include/boost/asio/detail/task_io_service.hpp | 3 +- .../boost/asio/detail/task_io_service_fwd.hpp | 30 - .../asio/detail/task_io_service_operation.hpp | 3 +- .../detail/task_io_service_thread_info.hpp | 4 +- include/boost/asio/detail/thread.hpp | 6 +- .../boost/asio/detail/timer_queue_base.hpp | 3 + include/boost/asio/detail/timer_queue_fwd.hpp | 29 - include/boost/asio/detail/timer_scheduler.hpp | 4 +- .../boost/asio/detail/timer_scheduler_fwd.hpp | 26 +- .../boost/asio/detail/variadic_templates.hpp | 63 ++ .../boost/asio/detail/win_iocp_io_service.hpp | 2 - .../asio/detail/win_iocp_io_service_fwd.hpp | 35 - .../boost/asio/detail/win_iocp_operation.hpp | 3 +- .../asio/detail/win_iocp_socket_service.hpp | 24 +- .../detail/win_iocp_socket_service_base.hpp | 12 +- .../asio/detail/win_object_handle_service.hpp | 2 +- .../boost/asio/detail/winrt_async_manager.hpp | 296 +++++++++ include/boost/asio/detail/winrt_async_op.hpp | 67 ++ .../boost/asio/detail/winrt_resolve_op.hpp | 119 ++++ .../asio/detail/winrt_resolver_service.hpp | 185 ++++++ .../asio/detail/winrt_socket_connect_op.hpp | 92 +++ .../asio/detail/winrt_socket_recv_op.hpp | 112 ++++ .../asio/detail/winrt_socket_send_op.hpp | 103 +++ .../asio/detail/winrt_ssocket_service.hpp | 234 +++++++ .../detail/winrt_ssocket_service_base.hpp | 357 ++++++++++ .../asio/detail/winrt_timer_scheduler.hpp | 133 ++++ include/boost/asio/detail/winrt_utils.hpp | 108 +++ include/boost/asio/detail/wrapped_handler.hpp | 2 +- include/boost/asio/error.hpp | 10 +- .../boost/asio/generic/datagram_protocol.hpp | 2 +- include/boost/asio/generic/raw_protocol.hpp | 2 +- .../asio/generic/seq_packet_protocol.hpp | 2 +- .../boost/asio/generic/stream_protocol.hpp | 2 +- include/boost/asio/handler_invoke_hook.hpp | 29 +- .../boost/asio/impl/buffered_read_stream.hpp | 360 ++++++++++ .../boost/asio/impl/buffered_write_stream.hpp | 340 ++++++++++ .../boost/asio/impl/handler_alloc_hook.ipp | 5 +- include/boost/asio/impl/serial_port_base.ipp | 1 - include/boost/asio/impl/src.hpp | 3 + include/boost/asio/io_service.hpp | 15 +- .../boost/asio/ip/basic_resolver_iterator.hpp | 69 +- .../boost/asio/ip/basic_resolver_query.hpp | 2 +- include/boost/asio/ip/detail/endpoint.hpp | 2 +- .../boost/asio/ip/detail/impl/endpoint.ipp | 16 +- include/boost/asio/ip/icmp.hpp | 8 +- include/boost/asio/ip/impl/address_v4.ipp | 5 +- include/boost/asio/ip/impl/address_v6.ipp | 5 +- include/boost/asio/ip/multicast.hpp | 27 +- include/boost/asio/ip/resolver_query_base.hpp | 32 +- include/boost/asio/ip/resolver_service.hpp | 12 +- include/boost/asio/ip/tcp.hpp | 10 +- include/boost/asio/ip/udp.hpp | 8 +- include/boost/asio/ip/unicast.hpp | 5 +- include/boost/asio/raw_socket_service.hpp | 10 +- .../boost/asio/seq_packet_socket_service.hpp | 35 +- .../boost/asio/socket_acceptor_service.hpp | 8 +- include/boost/asio/socket_base.hpp | 45 +- include/boost/asio/ssl/detail/io.hpp | 1 + include/boost/asio/stream_socket_service.hpp | 10 +- include/boost/asio/use_future.hpp | 6 +- .../windows/random_access_handle_service.hpp | 1 - include/boost/asio/write_at.hpp | 28 +- test/Jamfile | 3 +- test/Jamfile.v2 | 1 - test/buffered_read_stream.cpp | 109 ++++ test/buffered_stream.cpp | 120 ++++ test/buffered_write_stream.cpp | 109 ++++ test/deadline_timer.cpp | 4 +- test/generic/datagram_protocol.cpp | 33 +- test/generic/raw_protocol.cpp | 33 +- test/generic/seq_packet_protocol.cpp | 29 +- test/generic/stream_protocol.cpp | 41 +- test/io_service.cpp | 6 +- test/ip/icmp.cpp | 4 + test/ip/tcp.cpp | 12 +- test/ip/udp.cpp | 4 + test/ssl/Jamfile | 3 +- test/ssl/Jamfile.v2 | 1 - test/strand.cpp | 6 +- test/system_timer.cpp | 4 +- test/windows/random_access_handle.cpp | 2 +- 157 files changed, 6529 insertions(+), 1106 deletions(-) delete mode 100644 include/boost/asio/detail/dev_poll_reactor_fwd.hpp delete mode 100644 include/boost/asio/detail/epoll_reactor_fwd.hpp create mode 100644 include/boost/asio/detail/impl/buffer_sequence_adapter.ipp create mode 100644 include/boost/asio/detail/impl/winrt_ssocket_service_base.ipp create mode 100644 include/boost/asio/detail/impl/winrt_timer_scheduler.hpp create mode 100644 include/boost/asio/detail/impl/winrt_timer_scheduler.ipp delete mode 100644 include/boost/asio/detail/kqueue_reactor_fwd.hpp create mode 100644 include/boost/asio/detail/null_reactor.hpp create mode 100644 include/boost/asio/detail/null_socket_service.hpp delete mode 100644 include/boost/asio/detail/select_reactor_fwd.hpp delete mode 100644 include/boost/asio/detail/service_registry_fwd.hpp create mode 100644 include/boost/asio/detail/std_event.hpp create mode 100644 include/boost/asio/detail/std_mutex.hpp create mode 100644 include/boost/asio/detail/std_static_mutex.hpp create mode 100644 include/boost/asio/detail/std_thread.hpp delete mode 100644 include/boost/asio/detail/task_io_service_fwd.hpp delete mode 100644 include/boost/asio/detail/timer_queue_fwd.hpp create mode 100644 include/boost/asio/detail/variadic_templates.hpp delete mode 100644 include/boost/asio/detail/win_iocp_io_service_fwd.hpp create mode 100644 include/boost/asio/detail/winrt_async_manager.hpp create mode 100644 include/boost/asio/detail/winrt_async_op.hpp create mode 100644 include/boost/asio/detail/winrt_resolve_op.hpp create mode 100644 include/boost/asio/detail/winrt_resolver_service.hpp create mode 100644 include/boost/asio/detail/winrt_socket_connect_op.hpp create mode 100644 include/boost/asio/detail/winrt_socket_recv_op.hpp create mode 100644 include/boost/asio/detail/winrt_socket_send_op.hpp create mode 100644 include/boost/asio/detail/winrt_ssocket_service.hpp create mode 100644 include/boost/asio/detail/winrt_ssocket_service_base.hpp create mode 100644 include/boost/asio/detail/winrt_timer_scheduler.hpp create mode 100644 include/boost/asio/detail/winrt_utils.hpp create mode 100644 include/boost/asio/impl/buffered_read_stream.hpp create mode 100644 include/boost/asio/impl/buffered_write_stream.hpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index cde3e65c..3519a530 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -30,7 +30,7 @@ local example-names = cpp03/allocation cpp03/buffers cpp03/chat cpp03/echo cpp03/http/server3 cpp03/http/server4 cpp03/icmp cpp03/invocation cpp03/iostreams cpp03/local cpp03/multicast cpp03/nonblocking cpp03/porthopper cpp03/serialization cpp03/services cpp03/socks4 cpp03/spawn cpp03/ssl - cpp03/timeouts cpp03/timers cpp03/windows cpp11/allocaton cpp11/buffers + cpp03/timeouts cpp03/timers cpp03/windows cpp11/allocation cpp11/buffers cpp11/chat cpp11/echo cpp11/futures cpp11/http/server cpp11/spawn ; for local l in $(example-names) diff --git a/doc/overview/posix.qbk b/doc/overview/posix.qbk index bda30528..d944bac1 100644 --- a/doc/overview/posix.qbk +++ b/doc/overview/posix.qbk @@ -48,7 +48,7 @@ A client that connects to this server might look like: Transmission of file descriptors or credentials across UNIX domain sockets is not directly supported within Boost.Asio, but may be achieved by accessing the socket's underlying descriptor using the [link -boost_asio.reference.basic_socket.native native()] member function. +boost_asio.reference.basic_socket.native_handle native_handle()] member function. [heading See Also] diff --git a/doc/overview/serial_ports.qbk b/doc/overview/serial_ports.qbk index c6fd1246..d2399fa0 100644 --- a/doc/overview/serial_ports.qbk +++ b/doc/overview/serial_ports.qbk @@ -42,6 +42,6 @@ port's baud rate, flow control type, parity, stop bits and character size. Serial ports are available on all POSIX platforms. For Windows, serial ports are only available at compile time when the I/O completion port backend is used (which is the default). A program may test for the macro -`BOOST_ASIO_HAS_SERIAL_PORTS` to determine whether they are supported. +`BOOST_ASIO_HAS_SERIAL_PORT` to determine whether they are supported. [endsect] diff --git a/doc/reference.dox b/doc/reference.dox index e40c39f9..618b4a78 100644 --- a/doc/reference.dox +++ b/doc/reference.dox @@ -197,6 +197,7 @@ PREDEFINED = GENERATING_DOCUMENTATION \ BOOST_ASIO_OS_ERROR(e1,e2)=implementation_defined \ BOOST_ASIO_MOVE_ARG(a)=a \ BOOST_ASIO_DECL= \ + BOOST_ASIO_CONSTEXPR=constexpr \ BOOST_ASIO_INITFN_RESULT_TYPE(t,a)=void_or_deduced EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES diff --git a/doc/reference.qbk b/doc/reference.qbk index bacbf49d..f2a4fbc1 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -206,19 +206,25 @@ The default implementation of these allocation hooks uses `operator new` and `op [endsect] - [section:asio_handler_invoke asio_handler_invoke] [indexterm1 asio_handler_invoke] Default invoke function for handlers. + + template< + typename Function> + void ``[link boost_asio.reference.asio_handler_invoke.overload1 asio_handler_invoke]``( + Function & function, + ... ); + `` [''''»''' [link boost_asio.reference.asio_handler_invoke.overload1 more...]]`` template< typename Function> - void asio_handler_invoke( - Function function, + void ``[link boost_asio.reference.asio_handler_invoke.overload2 asio_handler_invoke]``( + const Function & function, ... ); - + `` [''''»''' [link boost_asio.reference.asio_handler_invoke.overload2 more...]]`` Completion handlers for asynchronous operations are invoked by the [link boost_asio.reference.io_service `io_service`] associated with the corresponding object (e.g. a socket or deadline\_timer). Certain guarantees are made on when the handler may be invoked, in particular that a handler can only be invoked from a thread that is currently calling `run()` on the corresponding [link boost_asio.reference.io_service `io_service`] object. Handlers may subsequently be invoked through other objects (such as [link boost_asio.reference.io_service__strand `io_service::strand`] objects) that provide additional guarantees. @@ -226,12 +232,12 @@ When asynchronous operations are composed from other asynchronous operations, al Implement asio\_handler\_invoke for your own handlers to specify a custom invocation strategy. -This default implementation is simply: - - function(); +This default implementation invokes the function object like so: + function(); +If necessary, the default implementation makes a copy of the function object so that the non-const operator() can be used. [heading Example] @@ -258,10 +264,44 @@ This default implementation is simply: ['Convenience header: ][^boost/asio.hpp] +[section:overload1 asio_handler_invoke (1 of 2 overloads)] + + +Default handler invocation hook used for non-const function objects. + + + template< + typename Function> + void asio_handler_invoke( + Function & function, + ... ); + + + [endsect] +[section:overload2 asio_handler_invoke (2 of 2 overloads)] + + +Default handler invocation hook used for const function objects. + + + template< + typename Function> + void asio_handler_invoke( + const Function & function, + ... ); + + + +[endsect] + + +[endsect] + + [section:asio_handler_is_continuation asio_handler_is_continuation] [indexterm1 asio_handler_is_continuation] @@ -2609,7 +2649,7 @@ This function is used to asynchronously write a certain number of bytes of data * An error occurred. -This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function. +This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function, and is known as a ['composed operation]. The program must ensure that the device performs no ['overlapping] write operations (such as async\_write\_at, the device's async\_write\_some\_at function, or any other composed operations that perform writes) until this operation completes. Operations are overlapping if the regions defined by their offsets, and the numbers of bytes to write, intersect. [heading Parameters] @@ -2682,7 +2722,7 @@ This function is used to asynchronously write a certain number of bytes of data * The completion\_condition function object returns 0. -This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function. +This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function, and is known as a ['composed operation]. The program must ensure that the device performs no ['overlapping] write operations (such as async\_write\_at, the device's async\_write\_some\_at function, or any other composed operations that perform writes) until this operation completes. Operations are overlapping if the regions defined by their offsets, and the numbers of bytes to write, intersect. [heading Parameters] @@ -2768,7 +2808,7 @@ This function is used to asynchronously write a certain number of bytes of data * An error occurred. -This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function. +This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function, and is known as a ['composed operation]. The program must ensure that the device performs no ['overlapping] write operations (such as async\_write\_at, the device's async\_write\_some\_at function, or any other composed operations that perform writes) until this operation completes. Operations are overlapping if the regions defined by their offsets, and the numbers of bytes to write, intersect. [heading Parameters] @@ -2831,7 +2871,7 @@ This function is used to asynchronously write a certain number of bytes of data * The completion\_condition function object returns 0. -This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function. +This operation is implemented in terms of zero or more calls to the device's async\_write\_some\_at function, and is known as a ['composed operation]. The program must ensure that the device performs no ['overlapping] write operations (such as async\_write\_at, the device's async\_write\_some\_at function, or any other composed operations that perform writes) until this operation completes. Operations are overlapping if the regions defined by their offsets, and the numbers of bytes to write, intersect. [heading Parameters] @@ -3645,7 +3685,7 @@ Regardless of whether the asynchronous operation completes immediately or not, t To receive into a single data buffer use the [link boost_asio.reference.buffer `buffer`] function as follows: socket.async_receive_from( - boost::asio::buffer(data, size), 0, sender_endpoint, handler); + boost::asio::buffer(data, size), sender_endpoint, handler); See the [link boost_asio.reference.buffer `buffer`] documentation for information on receiving into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. @@ -3802,7 +3842,7 @@ Start an asynchronous send on a connected socket. WriteHandler handler); -This function is used to send data on the datagram socket. The function call will block until the data has been sent successfully or an error occurs. +This function is used to asynchronously send data on the datagram socket. The function call always returns immediately. [heading Parameters] @@ -48643,7 +48683,7 @@ Start an asynchronous fill. template< typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_fill( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_fill( ReadHandler handler); @@ -48661,7 +48701,7 @@ Start an asynchronous read. The buffer into which the data will be read must be template< typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_read_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_read_some( const MutableBufferSequence & buffers, ReadHandler handler); @@ -48680,7 +48720,7 @@ Start an asynchronous write. The data being written must be valid for the lifeti template< typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_write_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_write_some( const ConstBufferSequence & buffers, WriteHandler handler); @@ -49346,7 +49386,7 @@ Start an asynchronous fill. template< typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_fill( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_fill( ReadHandler handler); @@ -49363,7 +49403,7 @@ Start an asynchronous flush. template< typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_flush( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_flush( WriteHandler handler); @@ -49381,7 +49421,7 @@ Start an asynchronous read. The buffer into which the data will be read must be template< typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_read_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_read_some( const MutableBufferSequence & buffers, ReadHandler handler); @@ -49400,7 +49440,7 @@ Start an asynchronous write. The data being written must be valid for the lifeti template< typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_write_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_write_some( const ConstBufferSequence & buffers, WriteHandler handler); @@ -50101,7 +50141,7 @@ Start an asynchronous flush. template< typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_flush( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_flush( WriteHandler handler); @@ -50119,7 +50159,7 @@ Start an asynchronous read. The buffer into which the data will be read must be template< typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_read_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_read_some( const MutableBufferSequence & buffers, ReadHandler handler); @@ -50138,7 +50178,7 @@ Start an asynchronous write. The data being written must be valid for the lifeti template< typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_write_some( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_write_some( const ConstBufferSequence & buffers, WriteHandler handler); @@ -65410,7 +65450,9 @@ The iterator type. [[link boost_asio.reference.ip__basic_resolver_iterator.create [*create]]] [Create an iterator from an addrinfo list returned by getaddrinfo. - Create an iterator from an endpoint, host name and service name. ] + Create an iterator from an endpoint, host name and service name. + + Create an iterator from a sequence of endpoints, host and service name. ] ] [ @@ -66185,7 +66227,9 @@ An iterator over the entries produced by a resolver. [[link boost_asio.reference.ip__basic_resolver_iterator.create [*create]]] [Create an iterator from an addrinfo list returned by getaddrinfo. - Create an iterator from an endpoint, host name and service name. ] + Create an iterator from an endpoint, host name and service name. + + Create an iterator from a sequence of endpoints, host and service name. ] ] [ @@ -66284,7 +66328,20 @@ Create an iterator from an endpoint, host name and service name. `` [''''»''' [link boost_asio.reference.ip__basic_resolver_iterator.create.overload2 more...]]`` -[section:overload1 ip::basic_resolver_iterator::create (1 of 2 overloads)] +Create an iterator from a sequence of endpoints, host and service name. + + + template< + typename ``[link boost_asio.reference.EndpointIterator EndpointIterator]``> + static basic_resolver_iterator ``[link boost_asio.reference.ip__basic_resolver_iterator.create.overload3 create]``( + EndpointIterator begin, + EndpointIterator end, + const std::string & host_name, + const std::string & service_name); + `` [''''»''' [link boost_asio.reference.ip__basic_resolver_iterator.create.overload3 more...]]`` + + +[section:overload1 ip::basic_resolver_iterator::create (1 of 3 overloads)] Create an iterator from an addrinfo list returned by getaddrinfo. @@ -66301,7 +66358,7 @@ Create an iterator from an addrinfo list returned by getaddrinfo. -[section:overload2 ip::basic_resolver_iterator::create (2 of 2 overloads)] +[section:overload2 ip::basic_resolver_iterator::create (2 of 3 overloads)] Create an iterator from an endpoint, host name and service name. @@ -66314,6 +66371,26 @@ Create an iterator from an endpoint, host name and service name. +[endsect] + + + +[section:overload3 ip::basic_resolver_iterator::create (3 of 3 overloads)] + + +Create an iterator from a sequence of endpoints, host and service name. + + + template< + typename ``[link boost_asio.reference.EndpointIterator EndpointIterator]``> + static basic_resolver_iterator create( + EndpointIterator begin, + EndpointIterator end, + const std::string & host_name, + const std::string & service_name); + + + [endsect] @@ -69029,7 +69106,9 @@ The iterator type. [[link boost_asio.reference.ip__basic_resolver_iterator.create [*create]]] [Create an iterator from an addrinfo list returned by getaddrinfo. - Create an iterator from an endpoint, host name and service name. ] + Create an iterator from an endpoint, host name and service name. + + Create an iterator from a sequence of endpoints, host and service name. ] ] [ @@ -83543,7 +83622,7 @@ Start an asynchronous receive. template< typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> - void async_receive( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_receive( implementation_type & impl, const MutableBufferSequence & buffers, socket_base::message_flags in_flags, @@ -83565,7 +83644,7 @@ Start an asynchronous send. template< typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> - void async_send( + ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` async_send( implementation_type & impl, const ConstBufferSequence & buffers, socket_base::message_flags flags, diff --git a/include/boost/asio/basic_datagram_socket.hpp b/include/boost/asio/basic_datagram_socket.hpp index a9b2211e..64fb4b06 100644 --- a/include/boost/asio/basic_datagram_socket.hpp +++ b/include/boost/asio/basic_datagram_socket.hpp @@ -350,9 +350,8 @@ public: /// Start an asynchronous send on a connected socket. /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. + * This function is used to asynchronously send data on the datagram socket. + * The function call always returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying @@ -878,7 +877,7 @@ public: * To receive into a single data buffer use the @ref buffer function as * follows: * @code socket.async_receive_from( - * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector. diff --git a/include/boost/asio/basic_socket_iostream.hpp b/include/boost/asio/basic_socket_iostream.hpp index 6135ea6a..8dcd3698 100644 --- a/include/boost/asio/basic_socket_iostream.hpp +++ b/include/boost/asio/basic_socket_iostream.hpp @@ -26,14 +26,7 @@ #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -# include -# include -# include -# include - -# if !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY) -# define BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY 5 -# endif // !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY) +# include // A macro that should expand to: // template @@ -48,16 +41,16 @@ // } // This macro should only persist within this file. -# define BOOST_ASIO_PRIVATE_CTR_DEF(z, n, data) \ - template \ - explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ +# define BOOST_ASIO_PRIVATE_CTR_DEF(n) \ + template \ + explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_PARAMS(n)) \ : std::basic_iostream( \ &this->detail::socket_iostream_base< \ Protocol, StreamSocketService, Time, \ TimeTraits, TimerService>::streambuf_) \ { \ this->setf(std::ios_base::unitbuf); \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ + if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \ this->setstate(std::ios_base::failbit); \ } \ /**/ @@ -71,11 +64,11 @@ // } // This macro should only persist within this file. -# define BOOST_ASIO_PRIVATE_CONNECT_DEF(z, n, data) \ - template \ - void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ +# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \ + template \ + void connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \ { \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ + if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \ this->setstate(std::ios_base::failbit); \ } \ /**/ @@ -175,9 +168,7 @@ public: this->setstate(std::ios_base::failbit); } #else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY), - BOOST_ASIO_PRIVATE_CTR_DEF, _ ) + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CTR_DEF) #endif #if defined(GENERATING_DOCUMENTATION) @@ -197,9 +188,7 @@ public: this->setstate(std::ios_base::failbit); } #else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY), - BOOST_ASIO_PRIVATE_CONNECT_DEF, _ ) + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF) #endif /// Close the connection. diff --git a/include/boost/asio/basic_socket_streambuf.hpp b/include/boost/asio/basic_socket_streambuf.hpp index eca21eb9..d7d55bcc 100644 --- a/include/boost/asio/basic_socket_streambuf.hpp +++ b/include/boost/asio/basic_socket_streambuf.hpp @@ -35,14 +35,7 @@ #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -# include -# include -# include -# include - -# if !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY) -# define BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY 5 -# endif // !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY) +# include // A macro that should expand to: // template @@ -60,17 +53,16 @@ // } // This macro should only persist within this file. -# define BOOST_ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \ - template \ +# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \ + template \ basic_socket_streambuf* connect( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ + Time, TimeTraits, TimerService>* connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \ { \ init_buffers(); \ this->basic_socket::close(ec_); \ typedef typename Protocol::resolver resolver_type; \ typedef typename resolver_type::query resolver_query; \ - resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \ + resolver_query query(BOOST_ASIO_VARIADIC_ARGS(n)); \ resolve_and_connect(query); \ return !ec_ ? this : 0; \ } \ @@ -216,9 +208,7 @@ public: return !ec_ ? this : 0; } #else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY), - BOOST_ASIO_PRIVATE_CONNECT_DEF, _ ) + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF) #endif /// Close the connection. diff --git a/include/boost/asio/buffered_read_stream.hpp b/include/boost/asio/buffered_read_stream.hpp index f53d583b..e7a85605 100644 --- a/include/boost/asio/buffered_read_stream.hpp +++ b/include/boost/asio/buffered_read_stream.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,7 @@ namespace asio { * @e Shared @e objects: Unsafe. * * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream. + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */ template class buffered_read_stream @@ -134,199 +135,65 @@ public: /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { - next_layer_.async_write_some(buffers, handler); + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + next_layer_.async_write_some(buffers, + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)))(init.handler)); + + return init.result.get(); } /// Fill the buffer with some data. Returns the number of bytes placed in the /// buffer as a result of the operation. Throws an exception on failure. - std::size_t fill() - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size))); - resize_guard.commit(); - return storage_.size() - previous_size; - } + std::size_t fill(); /// Fill the buffer with some data. Returns the number of bytes placed in the /// buffer as a result of the operation, or 0 if an error occurred. - std::size_t fill(boost::system::error_code& ec) - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - ec)); - resize_guard.commit(); - return storage_.size() - previous_size; - } - - template - class fill_handler - { - public: - fill_handler(boost::asio::io_service& io_service, - detail::buffered_stream_storage& storage, - std::size_t previous_size, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - previous_size_(previous_size), - handler_(handler) - { - } - - void operator()(const boost::system::error_code& ec, - std::size_t bytes_transferred) - { - storage_.resize(previous_size_ + bytes_transferred); - io_service_.dispatch(detail::bind_handler( - handler_, ec, bytes_transferred)); - } - - private: - boost::asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - std::size_t previous_size_; - ReadHandler handler_; - }; + std::size_t fill(boost::system::error_code& ec); /// Start an asynchronous fill. template - void async_fill(ReadHandler handler) - { - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - next_layer_.async_read_some( - buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - fill_handler(get_io_service(), - storage_, previous_size, handler)); - } + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_fill(BOOST_ASIO_MOVE_ARG(ReadHandler) handler); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure. template - std::size_t read_some(const MutableBufferSequence& buffers) - { - if (boost::asio::buffer_size(buffers) == 0) - return 0; - - if (storage_.empty()) - fill(); - - return copy(buffers); - } + std::size_t read_some(const MutableBufferSequence& buffers); /// Read some data from the stream. Returns the number of bytes read or 0 if /// an error occurred. template std::size_t read_some(const MutableBufferSequence& buffers, - boost::system::error_code& ec) - { - ec = boost::system::error_code(); - - if (boost::asio::buffer_size(buffers) == 0) - return 0; - - if (storage_.empty() && !fill(ec)) - return 0; - - return copy(buffers); - } - - template - class read_some_handler - { - public: - read_some_handler(boost::asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const MutableBufferSequence& buffers, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const boost::system::error_code& ec, std::size_t) - { - if (ec || storage_.empty()) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - std::size_t bytes_copied = boost::asio::buffer_copy( - buffers_, storage_.data(), storage_.size()); - storage_.consume(bytes_copied); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - boost::asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - MutableBufferSequence buffers_; - ReadHandler handler_; - }; + boost::system::error_code& ec); /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - if (boost::asio::buffer_size(buffers) == 0) - { - get_io_service().post(detail::bind_handler( - handler, boost::system::error_code(), 0)); - } - else if (storage_.empty()) - { - async_fill(read_some_handler( - get_io_service(), storage_, buffers, handler)); - } - else - { - std::size_t length = copy(buffers); - get_io_service().post(detail::bind_handler( - handler, boost::system::error_code(), length)); - } - } + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler); /// Peek at the incoming data on the stream. Returns the number of bytes read. /// Throws an exception on failure. template - std::size_t peek(const MutableBufferSequence& buffers) - { - if (storage_.empty()) - fill(); - return peek_copy(buffers); - } + std::size_t peek(const MutableBufferSequence& buffers); /// Peek at the incoming data on the stream. Returns the number of bytes read, /// or 0 if an error occurred. template std::size_t peek(const MutableBufferSequence& buffers, - boost::system::error_code& ec) - { - ec = boost::system::error_code(); - if (storage_.empty() && !fill(ec)) - return 0; - return peek_copy(buffers); - } + boost::system::error_code& ec); /// Determine the amount of data that may be read without blocking. std::size_t in_avail() @@ -374,4 +241,6 @@ private: #include +#include + #endif // BOOST_ASIO_BUFFERED_READ_STREAM_HPP diff --git a/include/boost/asio/buffered_stream.hpp b/include/boost/asio/buffered_stream.hpp index 19d40f11..0ff36ec1 100644 --- a/include/boost/asio/buffered_stream.hpp +++ b/include/boost/asio/buffered_stream.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -123,9 +124,12 @@ public: /// Start an asynchronous flush. template - void async_flush(WriteHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_flush(BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { - return stream_impl_.next_layer().async_flush(handler); + return stream_impl_.next_layer().async_flush( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); } /// Write the given data to the stream. Returns the number of bytes written. @@ -148,10 +152,13 @@ public: /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { - stream_impl_.async_write_some(buffers, handler); + return stream_impl_.async_write_some(buffers, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); } /// Fill the buffer with some data. Returns the number of bytes placed in the @@ -170,9 +177,11 @@ public: /// Start an asynchronous fill. template - void async_fill(ReadHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_fill(BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { - stream_impl_.async_fill(handler); + return stream_impl_.async_fill(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); } /// Read some data from the stream. Returns the number of bytes read. Throws @@ -195,10 +204,13 @@ public: /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { - stream_impl_.async_read_some(buffers, handler); + return stream_impl_.async_read_some(buffers, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); } /// Peek at the incoming data on the stream. Returns the number of bytes read. diff --git a/include/boost/asio/buffered_write_stream.hpp b/include/boost/asio/buffered_write_stream.hpp index e909a95b..e570161d 100644 --- a/include/boost/asio/buffered_write_stream.hpp +++ b/include/boost/asio/buffered_write_stream.hpp @@ -118,156 +118,37 @@ public: /// Flush all data from the buffer to the next layer. Returns the number of /// bytes written to the next layer on the last write operation. Throws an /// exception on failure. - std::size_t flush() - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size())); - storage_.consume(bytes_written); - return bytes_written; - } + std::size_t flush(); /// Flush all data from the buffer to the next layer. Returns the number of /// bytes written to the next layer on the last write operation, or 0 if an /// error occurred. - std::size_t flush(boost::system::error_code& ec) - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size()), - transfer_all(), ec); - storage_.consume(bytes_written); - return bytes_written; - } - - template - class flush_handler - { - public: - flush_handler(boost::asio::io_service& io_service, - detail::buffered_stream_storage& storage, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - handler_(handler) - { - } - - void operator()(const boost::system::error_code& ec, - std::size_t bytes_written) - { - storage_.consume(bytes_written); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written)); - } - - private: - boost::asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - WriteHandler handler_; - }; + std::size_t flush(boost::system::error_code& ec); /// Start an asynchronous flush. template - void async_flush(WriteHandler handler) - { - async_write(next_layer_, buffer(storage_.data(), storage_.size()), - flush_handler(get_io_service(), storage_, handler)); - } + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_flush(BOOST_ASIO_MOVE_ARG(WriteHandler) handler); /// Write the given data to the stream. Returns the number of bytes written. /// Throws an exception on failure. template - std::size_t write_some(const ConstBufferSequence& buffers) - { - if (boost::asio::buffer_size(buffers) == 0) - return 0; - - if (storage_.size() == storage_.capacity()) - flush(); - - return copy(buffers); - } + std::size_t write_some(const ConstBufferSequence& buffers); /// Write the given data to the stream. Returns the number of bytes written, /// or 0 if an error occurred and the error handler did not throw. template std::size_t write_some(const ConstBufferSequence& buffers, - boost::system::error_code& ec) - { - ec = boost::system::error_code(); - - if (boost::asio::buffer_size(buffers) == 0) - return 0; - - if (storage_.size() == storage_.capacity() && !flush(ec)) - return 0; - - return copy(buffers); - } - - template - class write_some_handler - { - public: - write_some_handler(boost::asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const ConstBufferSequence& buffers, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const boost::system::error_code& ec, std::size_t) - { - if (ec) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_avail = boost::asio::buffer_size(buffers_); - std::size_t length = bytes_avail < space_avail - ? bytes_avail : space_avail; - storage_.resize(orig_size + length); - std::size_t bytes_copied = boost::asio::buffer_copy( - storage_.data() + orig_size, buffers_, length); - - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - boost::asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - ConstBufferSequence buffers_; - WriteHandler handler_; - }; + boost::system::error_code& ec); /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - if (boost::asio::buffer_size(buffers) == 0) - { - get_io_service().post(detail::bind_handler( - handler, boost::system::error_code(), 0)); - } - else if (storage_.size() == storage_.capacity()) - { - async_flush(write_some_handler( - get_io_service(), storage_, buffers, handler)); - } - else - { - std::size_t bytes_copied = copy(buffers); - get_io_service().post(detail::bind_handler( - handler, boost::system::error_code(), bytes_copied)); - } - } + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure. @@ -289,10 +170,20 @@ public: /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { - next_layer_.async_read_some(buffers, handler); + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + next_layer_.async_read_some(buffers, + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)))(init.handler)); + + return init.result.get(); } /// Peek at the incoming data on the stream. Returns the number of bytes read. @@ -328,16 +219,7 @@ private: /// Copy data into the internal buffer from the specified source buffer. /// Returns the number of bytes copied. template - std::size_t copy(const ConstBufferSequence& buffers) - { - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_avail = boost::asio::buffer_size(buffers); - std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail; - storage_.resize(orig_size + length); - return boost::asio::buffer_copy( - storage_.data() + orig_size, buffers, length); - } + std::size_t copy(const ConstBufferSequence& buffers); /// The next layer. Stream next_layer_; @@ -351,4 +233,6 @@ private: #include +#include + #endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP diff --git a/include/boost/asio/datagram_socket_service.hpp b/include/boost/asio/datagram_socket_service.hpp index c3eb024f..e8ef5452 100644 --- a/include/boost/asio/datagram_socket_service.hpp +++ b/include/boost/asio/datagram_socket_service.hpp @@ -22,7 +22,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #else # include @@ -56,7 +58,9 @@ public: private: // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::null_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) typedef detail::win_iocp_socket_service service_impl_type; #else typedef detail::reactive_socket_service service_impl_type; @@ -138,7 +142,7 @@ public: boost::system::error_code open(implementation_type& impl, const protocol_type& protocol, boost::system::error_code& ec) { - if (protocol.type() == SOCK_DGRAM) + if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM)) service_impl_.open(impl, protocol, ec); else ec = boost::asio::error::invalid_argument; diff --git a/include/boost/asio/detail/buffer_sequence_adapter.hpp b/include/boost/asio/detail/buffer_sequence_adapter.hpp index edcce6df..a5001659 100644 --- a/include/boost/asio/detail/buffer_sequence_adapter.hpp +++ b/include/boost/asio/detail/buffer_sequence_adapter.hpp @@ -29,7 +29,23 @@ namespace detail { class buffer_sequence_adapter_base { protected: -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 1 }; + + typedef Windows::Storage::Streams::IBuffer^ native_buffer_type; + + BOOST_ASIO_DECL static void init_native_buffer( + native_buffer_type& buf, + const boost::asio::mutable_buffer& buffer); + + BOOST_ASIO_DECL static void init_native_buffer( + native_buffer_type& buf, + const boost::asio::const_buffer& buffer); +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + typedef WSABUF native_buffer_type; static void init_native_buffer(WSABUF& buf, @@ -46,6 +62,9 @@ protected: buf.len = static_cast(boost::asio::buffer_size(buffer)); } #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + typedef iovec native_buffer_type; static void init_iov_base(void*& base, void* addr) @@ -146,9 +165,6 @@ public: } private: - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; - native_buffer_type buffers_[max_buffers]; std::size_t count_; std::size_t total_buffer_size_; @@ -362,4 +378,8 @@ private: #include +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP diff --git a/include/boost/asio/detail/config.hpp b/include/boost/asio/detail/config.hpp index 6387558a..327622a1 100644 --- a/include/boost/asio/detail/config.hpp +++ b/include/boost/asio/detail/config.hpp @@ -97,6 +97,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_MOVE 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_MOVE) #endif // !defined(BOOST_ASIO_HAS_MOVE) @@ -152,6 +157,31 @@ # endif // !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES) #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +// Support constexpr on compilers known to allow it. +#if !defined(BOOST_ASIO_HAS_CONSTEXPR) +# if !defined(BOOST_ASIO_DISABLE_CONSTEXPR) +# if defined(__clang__) +# if __has_feature(__cxx_constexpr__) +# define BOOST_ASIO_HAS_CONSTEXPR 1 +# endif // __has_feature(__cxx_constexr__) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_CONSTEXPR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(BOOST_ASIO_DISABLE_CONSTEXPR) +#endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) +#if !defined(BOOST_ASIO_CONSTEXPR) +# if defined(BOOST_ASIO_HAS_CONSTEXPR) +# define BOOST_ASIO_CONSTEXPR constexpr +# else // defined(BOOST_ASIO_HAS_CONSTEXPR) +# define BOOST_ASIO_CONSTEXPR +# endif // defined(BOOST_ASIO_HAS_CONSTEXPR) +#endif // !defined(BOOST_ASIO_CONSTEXPR) + // Standard library support for system errors. # if !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR) # if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) @@ -164,6 +194,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR) // Compliant C++11 compilers put noexcept specifiers on error_category members. @@ -241,6 +276,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_ATOMIC) #endif // !defined(BOOST_ASIO_HAS_STD_ATOMIC) @@ -262,6 +302,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_CHRONO 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_CHRONO) #endif // !defined(BOOST_ASIO_HAS_STD_CHRONO) @@ -294,6 +339,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_ADDRESSOF 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_ADDRESSOF) #endif // !defined(BOOST_ASIO_HAS_STD_ADDRESSOF) @@ -310,6 +360,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_FUNCTION 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_FUNCTION) #endif // !defined(BOOST_ASIO_HAS_STD_FUNCTION) @@ -326,6 +381,11 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_TYPE_TRAITS 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_STD_TYPE_TRAITS) #endif // !defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) @@ -342,16 +402,74 @@ # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_CSTDINT 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_CSTDINT) #endif // !defined(BOOST_ASIO_HAS_CSTDINT) -// Windows target. +// Standard library support for the thread class. +#if !defined(BOOST_ASIO_HAS_STD_THREAD) +# if !defined(BOOST_ASIO_DISABLE_STD_THREAD) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_THREAD) +#endif // !defined(BOOST_ASIO_HAS_STD_THREAD) + +// Standard library support for the mutex and condition variable classes. +#if !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# if !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) +#endif // !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +// WinRT target. +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if defined(WINAPI_FAMILY) +# if ((WINAPI_FAMILY & WINAPI_PARTITION_APP) != 0) +# define BOOST_ASIO_WINDOWS_RUNTIME 1 +# endif // ((WINAPI_FAMILY & WINAPI_PARTITION_APP) != 0) +# endif // defined(WINAPI_FAMILY) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +// Windows target. Excludes WinRT. #if !defined(BOOST_ASIO_WINDOWS) -# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) -# define BOOST_ASIO_WINDOWS 1 -# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# define BOOST_ASIO_WINDOWS 1 -# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) +# if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) +# define BOOST_ASIO_WINDOWS 1 +# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define BOOST_ASIO_WINDOWS 1 +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) +# endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // !defined(BOOST_ASIO_WINDOWS) // Windows: target OS version. @@ -479,14 +597,18 @@ // Serial ports. #if !defined(BOOST_ASIO_HAS_SERIAL_PORT) # if defined(BOOST_ASIO_HAS_IOCP) \ - || !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + || !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) # if !defined(__SYMBIAN32__) # if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) # define BOOST_ASIO_HAS_SERIAL_PORT 1 # endif // !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) # endif // !defined(__SYMBIAN32__) # endif // defined(BOOST_ASIO_HAS_IOCP) - // || !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + // || !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) #endif // !defined(BOOST_ASIO_HAS_SERIAL_PORT) // Windows: stream handles. @@ -530,27 +652,39 @@ // POSIX: stream-oriented file descriptors. #if !defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) # if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) -# if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) # define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 -# endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) # endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) #endif // !defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) // UNIX domain sockets. #if !defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) # if !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) -# if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) # define BOOST_ASIO_HAS_LOCAL_SOCKETS 1 -# endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) # endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) #endif // !defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) // Can use sigaction() instead of signal(). #if !defined(BOOST_ASIO_HAS_SIGACTION) # if !defined(BOOST_ASIO_DISABLE_SIGACTION) -# if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) # define BOOST_ASIO_HAS_SIGACTION 1 -# endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) # endif // !defined(BOOST_ASIO_DISABLE_SIGACTION) #endif // !defined(BOOST_ASIO_HAS_SIGACTION) @@ -728,13 +862,23 @@ # if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) # if !defined(__INTEL_COMPILER) && !defined(__ICL) # define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define BOOST_ASIO_THREAD_KEYWORD __thread # elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) # define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 # endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) # endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) # endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) # endif // defined(__linux__) +# if defined(BOOST_ASIO_MSVC) && defined(WINAPI_FAMILY) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define BOOST_ASIO_THREAD_KEYWORD __declspec(thread) +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) && defined(WINAPI_FAMILY) #endif // !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) +#if !defined(BOOST_ASIO_THREAD_KEYWORD) +# define BOOST_ASIO_THREAD_KEYWORD __thread +#endif // !defined(BOOST_ASIO_THREAD_KEYWORD) // Support for POSIX ssize_t typedef. #if !defined(BOOST_ASIO_DISABLE_SSIZE_T) diff --git a/include/boost/asio/detail/deadline_timer_service.hpp b/include/boost/asio/detail/deadline_timer_service.hpp index 3be332c1..ab4e1c09 100644 --- a/include/boost/asio/detail/deadline_timer_service.hpp +++ b/include/boost/asio/detail/deadline_timer_service.hpp @@ -30,6 +30,11 @@ #include #include +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +# include +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + #include namespace boost { @@ -195,10 +200,17 @@ private: template void do_wait(const Duration& timeout, boost::system::error_code& ec) { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + std::this_thread::sleep_for( + std::chrono::seconds(timeout.total_seconds()) + + std::chrono::microseconds(timeout.total_microseconds())); + ec = boost::system::error_code(); +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) ::timeval tv; tv.tv_sec = timeout.total_seconds(); tv.tv_usec = timeout.total_microseconds() % 1000000; socket_ops::select(0, 0, 0, 0, &tv, ec); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } // The queue of timers. diff --git a/include/boost/asio/detail/descriptor_ops.hpp b/include/boost/asio/detail/descriptor_ops.hpp index b8edd5b6..5ac2a791 100644 --- a/include/boost/asio/detail/descriptor_ops.hpp +++ b/include/boost/asio/detail/descriptor_ops.hpp @@ -17,7 +17,9 @@ #include -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) #include #include @@ -110,6 +112,8 @@ BOOST_ASIO_DECL int poll_write(int d, # include #endif // defined(BOOST_ASIO_HEADER_ONLY) -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) #endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP diff --git a/include/boost/asio/detail/dev_poll_reactor.hpp b/include/boost/asio/detail/dev_poll_reactor.hpp index b82c4d8e..2fbf2d7d 100644 --- a/include/boost/asio/detail/dev_poll_reactor.hpp +++ b/include/boost/asio/detail/dev_poll_reactor.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/asio/detail/dev_poll_reactor_fwd.hpp b/include/boost/asio/detail/dev_poll_reactor_fwd.hpp deleted file mode 100644 index d3c10b9c..00000000 --- a/include/boost/asio/detail/dev_poll_reactor_fwd.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// detail/dev_poll_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP -#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include - -#if defined(BOOST_ASIO_HAS_DEV_POLL) - -namespace boost { -namespace asio { -namespace detail { - -class dev_poll_reactor; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // defined(BOOST_ASIO_HAS_DEV_POLL) - -#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP diff --git a/include/boost/asio/detail/epoll_reactor.hpp b/include/boost/asio/detail/epoll_reactor.hpp index 2a4f4c1d..d9df801f 100644 --- a/include/boost/asio/detail/epoll_reactor.hpp +++ b/include/boost/asio/detail/epoll_reactor.hpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -30,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/include/boost/asio/detail/epoll_reactor_fwd.hpp b/include/boost/asio/detail/epoll_reactor_fwd.hpp deleted file mode 100644 index 392ab455..00000000 --- a/include/boost/asio/detail/epoll_reactor_fwd.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// detail/epoll_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP -#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include - -#if defined(BOOST_ASIO_HAS_EPOLL) - -namespace boost { -namespace asio { -namespace detail { - -class epoll_reactor; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // defined(BOOST_ASIO_HAS_EPOLL) - -#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP diff --git a/include/boost/asio/detail/event.hpp b/include/boost/asio/detail/event.hpp index 5668410b..14d8d20e 100644 --- a/include/boost/asio/detail/event.hpp +++ b/include/boost/asio/detail/event.hpp @@ -23,8 +23,10 @@ # include #elif defined(BOOST_ASIO_HAS_PTHREADS) # include +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# include #else -# error Only Windows and POSIX are supported! +# error Only Windows, POSIX and std::condition_variable are supported! #endif namespace boost { @@ -37,6 +39,8 @@ typedef null_event event; typedef win_event event; #elif defined(BOOST_ASIO_HAS_PTHREADS) typedef posix_event event; +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +typedef std_event event; #endif } // namespace detail diff --git a/include/boost/asio/detail/fd_set_adapter.hpp b/include/boost/asio/detail/fd_set_adapter.hpp index 7e25b2fc..7362794b 100644 --- a/include/boost/asio/detail/fd_set_adapter.hpp +++ b/include/boost/asio/detail/fd_set_adapter.hpp @@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #include #include @@ -33,4 +36,6 @@ typedef posix_fd_set_adapter fd_set_adapter; } // namespace asio } // namespace boost +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #endif // BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP diff --git a/include/boost/asio/detail/handler_type_requirements.hpp b/include/boost/asio/detail/handler_type_requirements.hpp index 3046855a..c07ce1c2 100644 --- a/include/boost/asio/detail/handler_type_requirements.hpp +++ b/include/boost/asio/detail/handler_type_requirements.hpp @@ -53,6 +53,16 @@ # include #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) +// Newer gcc needs special treatment to suppress unused typedef warnings. +#if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__)) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +#endif // defined(__GNUC__) +#if !defined(BOOST_ASIO_UNUSED_TYPEDEF) +# define BOOST_ASIO_UNUSED_TYPEDEF +#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF) + namespace boost { namespace asio { namespace detail { @@ -131,7 +141,7 @@ struct handler_type_requirements sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()(), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ @@ -158,7 +168,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ @@ -186,7 +196,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ @@ -211,7 +221,7 @@ struct handler_type_requirements boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ @@ -236,7 +246,7 @@ struct handler_type_requirements boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ @@ -263,7 +273,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, iter_type) \ @@ -290,7 +300,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ @@ -315,7 +325,7 @@ struct handler_type_requirements boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ @@ -342,7 +352,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ @@ -367,7 +377,7 @@ struct handler_type_requirements boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ @@ -394,7 +404,7 @@ struct handler_type_requirements asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ @@ -419,57 +429,57 @@ struct handler_type_requirements boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ - char(0))> + char(0))> BOOST_ASIO_UNUSED_TYPEDEF #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, iter_type) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ - typedef int + typedef int BOOST_ASIO_UNUSED_TYPEDEF #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) diff --git a/include/boost/asio/detail/impl/buffer_sequence_adapter.ipp b/include/boost/asio/detail/impl/buffer_sequence_adapter.ipp new file mode 100644 index 00000000..322a3728 --- /dev/null +++ b/include/boost/asio/detail/impl/buffer_sequence_adapter.ipp @@ -0,0 +1,120 @@ +// +// detail/impl/buffer_sequence_adapter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP +#define BOOST_ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class winrt_buffer_impl : + public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>, + ABI::Windows::Storage::Streams::IBuffer, + Windows::Storage::Streams::IBufferByteAccess> +{ +public: + explicit winrt_buffer_impl(const boost::asio::const_buffer& b) + { + bytes_ = const_cast(boost::asio::buffer_cast(b)); + length_ = boost::asio::buffer_size(b); + capacity_ = boost::asio::buffer_size(b); + } + + explicit winrt_buffer_impl(const boost::asio::mutable_buffer& b) + { + bytes_ = const_cast(boost::asio::buffer_cast(b)); + length_ = 0; + capacity_ = boost::asio::buffer_size(b); + } + + ~winrt_buffer_impl() + { + } + + STDMETHODIMP Buffer(byte** value) + { + *value = bytes_; + return S_OK; + } + + STDMETHODIMP get_Capacity(UINT32* value) + { + *value = capacity_; + return S_OK; + } + + STDMETHODIMP get_Length(UINT32 *value) + { + *value = length_; + return S_OK; + } + + STDMETHODIMP put_Length(UINT32 value) + { + if (value > capacity_) + return E_INVALIDARG; + length_ = value; + return S_OK; + } + +private: + byte* bytes_; + UINT32 length_; + UINT32 capacity_; +}; + +void buffer_sequence_adapter_base::init_native_buffer( + buffer_sequence_adapter_base::native_buffer_type& buf, + const boost::asio::mutable_buffer& buffer) +{ + std::memset(&buf, 0, sizeof(native_buffer_type)); + Microsoft::WRL::ComPtr insp + = Microsoft::WRL::Make(buffer); + buf = reinterpret_cast(insp.Get()); +} + +void buffer_sequence_adapter_base::init_native_buffer( + buffer_sequence_adapter_base::native_buffer_type& buf, + const boost::asio::const_buffer& buffer) +{ + std::memset(&buf, 0, sizeof(native_buffer_type)); + Microsoft::WRL::ComPtr insp + = Microsoft::WRL::Make(buffer); + Platform::Object^ buf_obj = reinterpret_cast(insp.Get()); + buf = reinterpret_cast(insp.Get()); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP diff --git a/include/boost/asio/detail/impl/descriptor_ops.ipp b/include/boost/asio/detail/impl/descriptor_ops.ipp index 7dea8d45..756cfc3e 100644 --- a/include/boost/asio/detail/impl/descriptor_ops.ipp +++ b/include/boost/asio/detail/impl/descriptor_ops.ipp @@ -20,7 +20,9 @@ #include #include -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) #include @@ -444,6 +446,8 @@ int poll_write(int d, state_type state, boost::system::error_code& ec) #include -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) #endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP diff --git a/include/boost/asio/detail/impl/handler_tracking.ipp b/include/boost/asio/detail/impl/handler_tracking.ipp index fc21cee0..15692fdb 100644 --- a/include/boost/asio/detail/impl/handler_tracking.ipp +++ b/include/boost/asio/detail/impl/handler_tracking.ipp @@ -158,7 +158,7 @@ void handler_tracking::completion::invocation_begin() #else // defined(BOOST_ASIO_WINDOWS) "@asio|%llu.%06llu|>%llu|\n", #endif // defined(BOOST_ASIO_WINDOWS) - timestamp.seconds, timestamp.microseconds); + timestamp.seconds, timestamp.microseconds, id_); invoked_ = true; } @@ -244,7 +244,7 @@ void handler_tracking::completion::invocation_end() #else // defined(BOOST_ASIO_WINDOWS) "@asio|%llu.%06llu|<%llu|\n", #endif // defined(BOOST_ASIO_WINDOWS) - timestamp.seconds, timestamp.microseconds); + timestamp.seconds, timestamp.microseconds, id_); id_ = 0; } diff --git a/include/boost/asio/detail/impl/pipe_select_interrupter.ipp b/include/boost/asio/detail/impl/pipe_select_interrupter.ipp index af5177b9..4b4e02d1 100644 --- a/include/boost/asio/detail/impl/pipe_select_interrupter.ipp +++ b/include/boost/asio/detail/impl/pipe_select_interrupter.ipp @@ -17,6 +17,7 @@ #include +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if !defined(BOOST_ASIO_WINDOWS) #if !defined(__CYGWIN__) #if !defined(__SYMBIAN32__) @@ -120,5 +121,6 @@ bool pipe_select_interrupter::reset() #endif // !defined(__SYMBIAN32__) #endif // !defined(__CYGWIN__) #endif // !defined(BOOST_ASIO_WINDOWS) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // BOOST_ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP diff --git a/include/boost/asio/detail/impl/reactive_descriptor_service.ipp b/include/boost/asio/detail/impl/reactive_descriptor_service.ipp index 48e2784c..222ab06b 100644 --- a/include/boost/asio/detail/impl/reactive_descriptor_service.ipp +++ b/include/boost/asio/detail/impl/reactive_descriptor_service.ipp @@ -17,7 +17,9 @@ #include -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) #include #include @@ -201,6 +203,8 @@ void reactive_descriptor_service::start_op( #include -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) #endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP diff --git a/include/boost/asio/detail/impl/reactive_socket_service_base.ipp b/include/boost/asio/detail/impl/reactive_socket_service_base.ipp index fe7d7446..aac1aa09 100644 --- a/include/boost/asio/detail/impl/reactive_socket_service_base.ipp +++ b/include/boost/asio/detail/impl/reactive_socket_service_base.ipp @@ -17,7 +17,8 @@ #include -#if !defined(BOOST_ASIO_HAS_IOCP) +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #include @@ -263,5 +264,6 @@ void reactive_socket_service_base::start_connect_op( #include #endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP diff --git a/include/boost/asio/detail/impl/select_reactor.hpp b/include/boost/asio/detail/impl/select_reactor.hpp index 96e14b12..a691e43d 100644 --- a/include/boost/asio/detail/impl/select_reactor.hpp +++ b/include/boost/asio/detail/impl/select_reactor.hpp @@ -20,7 +20,8 @@ #if defined(BOOST_ASIO_HAS_IOCP) \ || (!defined(BOOST_ASIO_HAS_DEV_POLL) \ && !defined(BOOST_ASIO_HAS_EPOLL) \ - && !defined(BOOST_ASIO_HAS_KQUEUE)) + && !defined(BOOST_ASIO_HAS_KQUEUE) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #include @@ -82,6 +83,7 @@ std::size_t select_reactor::cancel_timer(timer_queue& queue, #endif // defined(BOOST_ASIO_HAS_IOCP) // || (!defined(BOOST_ASIO_HAS_DEV_POLL) // && !defined(BOOST_ASIO_HAS_EPOLL) - // && !defined(BOOST_ASIO_HAS_KQUEUE)) + // && !defined(BOOST_ASIO_HAS_KQUEUE) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #endif // BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP diff --git a/include/boost/asio/detail/impl/select_reactor.ipp b/include/boost/asio/detail/impl/select_reactor.ipp index 4b2f0300..18de41ac 100644 --- a/include/boost/asio/detail/impl/select_reactor.ipp +++ b/include/boost/asio/detail/impl/select_reactor.ipp @@ -20,7 +20,8 @@ #if defined(BOOST_ASIO_HAS_IOCP) \ || (!defined(BOOST_ASIO_HAS_DEV_POLL) \ && !defined(BOOST_ASIO_HAS_EPOLL) \ - && !defined(BOOST_ASIO_HAS_KQUEUE)) + && !defined(BOOST_ASIO_HAS_KQUEUE) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #include #include @@ -311,5 +312,6 @@ void select_reactor::cancel_ops_unlocked(socket_type descriptor, // || (!defined(BOOST_ASIO_HAS_DEV_POLL) // && !defined(BOOST_ASIO_HAS_EPOLL) // && !defined(BOOST_ASIO_HAS_KQUEUE)) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #endif // BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP diff --git a/include/boost/asio/detail/impl/signal_set_service.ipp b/include/boost/asio/detail/impl/signal_set_service.ipp index 131b5af0..643ab9c4 100644 --- a/include/boost/asio/detail/impl/signal_set_service.ipp +++ b/include/boost/asio/detail/impl/signal_set_service.ipp @@ -57,25 +57,33 @@ signal_state* get_signal_state() return &state; } -void asio_signal_handler(int signal_number) +void boost_asio_signal_handler(int signal_number) { -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + || defined(__CYGWIN__) signal_set_service::deliver_signal(signal_number); -#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(BOOST_ASIO_WINDOWS_RUNTIME) + // || defined(__CYGWIN__) int saved_errno = errno; signal_state* state = get_signal_state(); signed_size_type result = ::write(state->write_descriptor_, &signal_number, sizeof(signal_number)); (void)result; errno = saved_errno; -#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(BOOST_ASIO_WINDOWS_RUNTIME) + // || defined(__CYGWIN__) #if defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION) - ::signal(signal_number, asio_signal_handler); + ::signal(signal_number, boost_asio_signal_handler); #endif // defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION) } -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) class signal_set_service::pipe_read_op : public reactor_op { public: @@ -105,22 +113,32 @@ public: delete o; } }; -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) signal_set_service::signal_set_service( boost::asio::io_service& io_service) : io_service_(boost::asio::use_service(io_service)), -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) reactor_(boost::asio::use_service(io_service)), -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) next_(0), prev_(0) { get_signal_state()->mutex_.init(); -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) reactor_.init_task(); -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) for (int i = 0; i < max_signal_number; ++i) registrations_[i] = 0; @@ -155,7 +173,9 @@ void signal_set_service::shutdown_service() void signal_set_service::fork_service( boost::asio::io_service::fork_event fork_ev) { -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) signal_state* state = get_signal_state(); static_mutex::scoped_lock lock(state->mutex_); @@ -195,9 +215,13 @@ void signal_set_service::fork_service( default: break; } -#else // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#else // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) (void)fork_ev; -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) } void signal_set_service::construct( @@ -250,11 +274,11 @@ boost::system::error_code signal_set_service::add( using namespace std; // For memset. struct sigaction sa; memset(&sa, 0, sizeof(sa)); - sa.sa_handler = asio_signal_handler; + sa.sa_handler = boost_asio_signal_handler; sigfillset(&sa.sa_mask); if (::sigaction(signal_number, &sa, 0) == -1) # else // defined(BOOST_ASIO_HAS_SIGACTION) - if (::signal(signal_number, asio_signal_handler) == SIG_ERR) + if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR) # endif // defined(BOOST_ASIO_HAS_SIGACTION) { # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) @@ -489,13 +513,17 @@ void signal_set_service::add_service(signal_set_service* service) state->service_list_->prev_ = service; state->service_list_ = service; -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) // Register for pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock(); service->reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, service->reactor_data_, new pipe_read_op); -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) } void signal_set_service::remove_service(signal_set_service* service) @@ -505,14 +533,18 @@ void signal_set_service::remove_service(signal_set_service* service) if (service->next_ || service->prev_ || state->service_list_ == service) { -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) // Disable the pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock(); service->reactor_.deregister_descriptor( read_descriptor, service->reactor_data_, false); lock.lock(); -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) // Remove service from linked list of all services. if (state->service_list_ == service) @@ -534,7 +566,9 @@ void signal_set_service::remove_service(signal_set_service* service) void signal_set_service::open_descriptors() { -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) signal_state* state = get_signal_state(); int pipe_fds[2]; @@ -557,12 +591,16 @@ void signal_set_service::open_descriptors() boost::asio::error::get_system_category()); boost::asio::detail::throw_error(ec, "signal_set_service pipe"); } -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) } void signal_set_service::close_descriptors() { -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) signal_state* state = get_signal_state(); if (state->read_descriptor_ != -1) @@ -572,7 +610,9 @@ void signal_set_service::close_descriptors() if (state->write_descriptor_ != -1) ::close(state->write_descriptor_); state->write_descriptor_ = -1; -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) } void signal_set_service::start_wait_op( @@ -589,6 +629,7 @@ void signal_set_service::start_wait_op( if (reg->undelivered_ > 0) { --reg->undelivered_; + op->signal_number_ = reg->signal_number_; io_service_.post_deferred_completion(op); return; } diff --git a/include/boost/asio/detail/impl/socket_ops.ipp b/include/boost/asio/detail/impl/socket_ops.ipp index 5516d1c5..d6cc2b73 100644 --- a/include/boost/asio/detail/impl/socket_ops.ipp +++ b/include/boost/asio/detail/impl/socket_ops.ipp @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include + #include #include #include @@ -26,6 +27,12 @@ #include #include +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +# include +# include +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) \ || defined(__MACH__) && defined(__APPLE__) # if defined(BOOST_ASIO_HAS_PTHREADS) @@ -41,6 +48,8 @@ namespace asio { namespace detail { namespace socket_ops { +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) struct msghdr { int msg_namelen; }; #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) @@ -52,6 +61,8 @@ extern "C" char* if_indextoname(unsigned int, char*); extern "C" unsigned int if_nametoindex(const char*); #endif // defined(__hpux) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + inline void clear_last_error() { #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) @@ -61,6 +72,8 @@ inline void clear_last_error() #endif } +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + template inline ReturnType error_wrapper(ReturnType return_value, boost::system::error_code& ec) @@ -508,14 +521,35 @@ void sync_connect(socket_type s, const socket_addr_type* addr, boost::asio::error::get_system_category()); } -bool non_blocking_connect(socket_type s, - const socket_addr_type* addr, std::size_t addrlen, - boost::system::error_code& ec) +bool non_blocking_connect(socket_type s, boost::system::error_code& ec) { // Check if the connect operation has finished. This is required since we may // get spurious readiness notifications from the reactor. - socket_ops::connect(s, addr, addrlen, ec); - if (ec == boost::asio::error::already_started) +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(__SYMBIAN32__) + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(s, &write_fds); + fd_set except_fds; + FD_ZERO(&except_fds); + FD_SET(s, &except_fds); + timeval zero_timeout; + zero_timeout.tv_sec = 0; + zero_timeout.tv_usec = 0; + int ready = ::select(s + 1, 0, &write_fds, &except_fds, &zero_timeout); +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + int ready = ::poll(&fds, 1, 0); +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (ready == 0) { // The asynchronous connect operation is still in progress. return false; @@ -1313,7 +1347,7 @@ socket_type socket(int af, int type, int protocol, if (s == invalid_socket) return s; - if (af == AF_INET6) + if (af == BOOST_ASIO_OS_DEF(AF_INET6)) { // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to // false. This will only succeed on Windows Vista and later versions of @@ -1731,7 +1765,7 @@ int poll_read(socket_type s, state_type state, boost::system::error_code& ec) zero_timeout.tv_usec = 0; timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; clear_last_error(); - int result = error_wrapper(::select(s, &fds, 0, 0, timeout), ec); + int result = error_wrapper(::select(s + 1, &fds, 0, 0, timeout), ec); #else // defined(BOOST_ASIO_WINDOWS) // || defined(__CYGWIN__) // || defined(__SYMBIAN32__) @@ -1772,7 +1806,7 @@ int poll_write(socket_type s, state_type state, boost::system::error_code& ec) zero_timeout.tv_usec = 0; timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; clear_last_error(); - int result = error_wrapper(::select(s, 0, &fds, 0, timeout), ec); + int result = error_wrapper(::select(s + 1, 0, &fds, 0, timeout), ec); #else // defined(BOOST_ASIO_WINDOWS) // || defined(__CYGWIN__) // || defined(__SYMBIAN32__) @@ -1812,7 +1846,8 @@ int poll_connect(socket_type s, boost::system::error_code& ec) FD_ZERO(&except_fds); FD_SET(s, &except_fds); clear_last_error(); - int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec); + int result = error_wrapper(::select( + s + 1, 0, &write_fds, &except_fds, 0), ec); if (result >= 0) ec = boost::system::error_code(); return result; @@ -1833,14 +1868,51 @@ int poll_connect(socket_type s, boost::system::error_code& ec) // || defined(__SYMBIAN32__) } +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + const char* inet_ntop(int af, const void* src, char* dest, size_t length, unsigned long scope_id, boost::system::error_code& ec) { clear_last_error(); -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + using namespace std; // For sprintf. + const unsigned char* bytes = static_cast(src); + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + sprintf_s(dest, length, "%u.%u.%u.%u", + bytes[0], bytes[1], bytes[2], bytes[3]); + return dest; + } + else if (af == BOOST_ASIO_OS_DEF(AF_INET6)) + { + size_t n = 0, b = 0, z = 0; + while (n < length && b < 16) + { + if (bytes[b] == 0 && bytes[b + 1] == 0 && z == 0) + { + do b += 2; while (b < 16 && bytes[b] == 0 && bytes[b + 1] == 0); + n += sprintf_s(dest + n, length - n, ":%s", b < 16 ? "" : ":"), ++z; + } + else + { + n += sprintf_s(dest + n, length - n, "%s%x", b ? ":" : "", + (static_cast(bytes[b]) << 8) | bytes[b + 1]); + b += 2; + } + } + if (scope_id) + n += sprintf_s(dest + n, length - n, "%%%lu", scope_id); + return dest; + } + else + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) using namespace std; // For memcpy. - if (af != AF_INET && af != AF_INET6) + if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6)) { ec = boost::asio::error::address_family_not_supported; return 0; @@ -1854,17 +1926,17 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length, sockaddr_in6_type v6; } address; DWORD address_length; - if (af == AF_INET) + if (af == BOOST_ASIO_OS_DEF(AF_INET)) { address_length = sizeof(sockaddr_in4_type); - address.v4.sin_family = AF_INET; + address.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); address.v4.sin_port = 0; memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type)); } else // AF_INET6 { address_length = sizeof(sockaddr_in6_type); - address.v6.sin6_family = AF_INET6; + address.v6.sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); address.v6.sin6_port = 0; address.v6.sin6_flowinfo = 0; address.v6.sin6_scope_id = scope_id; @@ -1896,7 +1968,7 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length, af, src, dest, static_cast(length)), ec); if (result == 0 && !ec) ec = boost::asio::error::invalid_argument; - if (result != 0 && af == AF_INET6 && scope_id != 0) + if (result != 0 && af == BOOST_ASIO_OS_DEF(AF_INET6) && scope_id != 0) { using namespace std; // For strcat and sprintf. char if_name[IF_NAMESIZE + 1] = "%"; @@ -1916,10 +1988,154 @@ int inet_pton(int af, const char* src, void* dest, unsigned long* scope_id, boost::system::error_code& ec) { clear_last_error(); -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + using namespace std; // For sscanf. + unsigned char* bytes = static_cast(dest); + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + unsigned int b0, b1, b2, b3; + if (sscanf_s(src, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) != 4) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + if (b0 > 255 || b1 > 255 || b2 > 255 || b3 > 255) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + bytes[0] = static_cast(b0); + bytes[1] = static_cast(b1); + bytes[2] = static_cast(b2); + bytes[3] = static_cast(b3); + ec = boost::system::error_code(); + return 1; + } + else if (af == BOOST_ASIO_OS_DEF(AF_INET6)) + { + unsigned char* bytes = static_cast(dest); + std::memset(bytes, 0, 16); + unsigned char back_bytes[16] = { 0 }; + int num_front_bytes = 0, num_back_bytes = 0; + const char* p = src; + + enum { fword, fcolon, bword, scope, done } state = fword; + unsigned long current_word = 0; + while (state != done) + { + if (current_word > 0xFFFF) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + switch (state) + { + case fword: + if (*p >= '0' && *p <= '9') + current_word = current_word * 16 + *p++ - '0'; + else if (*p >= 'a' && *p <= 'f') + current_word = current_word * 16 + *p++ - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + current_word = current_word * 16 + *p++ - 'A' + 10; + else + { + if (num_front_bytes == 16) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + bytes[num_front_bytes++] = (current_word >> 8) & 0xFF; + bytes[num_front_bytes++] = current_word & 0xFF; + current_word = 0; + + if (*p == ':') + state = fcolon, ++p; + else if (*p == '%') + state = scope, ++p; + else if (*p == 0) + state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + } + break; + + case fcolon: + if (*p == ':') + state = bword, ++p; + else + state = fword; + break; + + case bword: + if (*p >= '0' && *p <= '9') + current_word = current_word * 16 + *p++ - '0'; + else if (*p >= 'a' && *p <= 'f') + current_word = current_word * 16 + *p++ - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + current_word = current_word * 16 + *p++ - 'A' + 10; + else + { + if (num_front_bytes + num_back_bytes == 16) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + back_bytes[num_back_bytes++] = (current_word >> 8) & 0xFF; + back_bytes[num_back_bytes++] = current_word & 0xFF; + current_word = 0; + + if (*p == ':') + state = bword, ++p; + else if (*p == '%') + state = scope, ++p; + else if (*p == 0) + state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + } + break; + + case scope: + if (*p >= '0' && *p <= '9') + current_word = current_word * 10 + *p++ - '0'; + else if (*p == 0) + *scope_id = current_word, state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + break; + + default: + break; + } + } + + for (int i = 0; i < num_back_bytes; ++i) + bytes[16 - num_back_bytes + i] = back_bytes[i]; + + ec = boost::system::error_code(); + return 1; + } + else + { + ec = boost::asio::error::address_family_not_supported; + return -1; + } +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) using namespace std; // For memcpy and strcmp. - if (af != AF_INET && af != AF_INET6) + if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6)) { ec = boost::asio::error::address_family_not_supported; return -1; @@ -1944,7 +2160,7 @@ int inet_pton(int af, const char* src, void* dest, const_cast(src), af, 0, &address.base, &address_length), ec); #endif - if (af == AF_INET) + if (af == BOOST_ASIO_OS_DEF(AF_INET)) { if (result != socket_error_retval) { @@ -1980,7 +2196,7 @@ int inet_pton(int af, const char* src, void* dest, int result = error_wrapper(::inet_pton(af, src, dest), ec); if (result <= 0 && !ec) ec = boost::asio::error::invalid_argument; - if (result > 0 && af == AF_INET6 && scope_id) + if (result > 0 && af == BOOST_ASIO_OS_DEF(AF_INET6) && scope_id) { using namespace std; // For strchr and atoi. *scope_id = 0; @@ -2002,14 +2218,47 @@ int inet_pton(int af, const char* src, void* dest, int gethostname(char* name, int namelen, boost::system::error_code& ec) { clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + try + { + using namespace Windows::Foundation::Collections; + using namespace Windows::Networking; + using namespace Windows::Networking::Connectivity; + IVectorView^ hostnames = NetworkInformation::GetHostNames(); + for (unsigned i = 0; i < hostnames->Size; ++i) + { + HostName^ hostname = hostnames->GetAt(i); + if (hostname->Type == HostNameType::DomainName) + { + std::wstring_convert> converter; + std::string raw_name = converter.to_bytes(hostname->RawName->Data()); + if (namelen > 0 && raw_name.size() < static_cast(namelen)) + { + strcpy_s(name, namelen, raw_name.c_str()); + return 0; + } + } + } + return -1; + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return -1; + } +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) int result = error_wrapper(::gethostname(name, namelen), ec); -#if defined(BOOST_ASIO_WINDOWS) +# if defined(BOOST_ASIO_WINDOWS) if (result == 0) ec = boost::system::error_code(); -#endif +# endif // defined(BOOST_ASIO_WINDOWS) return result; +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) \ || defined(__MACH__) && defined(__APPLE__) @@ -2087,7 +2336,7 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result, (void)(buffer); (void)(buflength); (void)(ai_flags); - if (af != AF_INET) + if (af != BOOST_ASIO_OS_DEF(AF_INET)) { ec = boost::asio::error::address_family_not_supported; return 0; @@ -2100,7 +2349,7 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result, return result; #elif defined(__sun) || defined(__QNX__) (void)(ai_flags); - if (af != AF_INET) + if (af != BOOST_ASIO_OS_DEF(AF_INET)) { ec = boost::asio::error::address_family_not_supported; return 0; @@ -2125,7 +2374,7 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result, return retval; #else (void)(ai_flags); - if (af != AF_INET) + if (af != BOOST_ASIO_OS_DEF(AF_INET)) { ec = boost::asio::error::address_family_not_supported; return 0; @@ -2170,22 +2419,22 @@ inline int gai_nsearch(const char* host, // No host and AI_PASSIVE implies wildcard bind. switch (hints->ai_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; break; - case AF_UNSPEC: + case BOOST_ASIO_OS_DEF(AF_UNSPEC): search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; default: @@ -2197,22 +2446,22 @@ inline int gai_nsearch(const char* host, // No host and not AI_PASSIVE means connect to local host. switch (hints->ai_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): search[search_count].host = "localhost"; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; break; - case AF_UNSPEC: + case BOOST_ASIO_OS_DEF(AF_UNSPEC): search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; search[search_count].host = "localhost"; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; default: @@ -2225,22 +2474,22 @@ inline int gai_nsearch(const char* host, // Host is specified. switch (hints->ai_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): search[search_count].host = host; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): search[search_count].host = host; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; break; - case AF_UNSPEC: + case BOOST_ASIO_OS_DEF(AF_UNSPEC): search[search_count].host = host; - search[search_count].family = AF_INET6; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); ++search_count; search[search_count].host = host; - search[search_count].family = AF_INET; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); ++search_count; break; default: @@ -2300,23 +2549,23 @@ inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, switch (ai->ai_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): { sockaddr_in4_type* sinptr = gai_alloc(); if (sinptr == 0) return EAI_MEMORY; - sinptr->sin_family = AF_INET; + sinptr->sin_family = BOOST_ASIO_OS_DEF(AF_INET); memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); ai->ai_addr = reinterpret_cast(sinptr); ai->ai_addrlen = sizeof(sockaddr_in4_type); break; } - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): { sockaddr_in6_type* sin6ptr = gai_alloc(); if (sin6ptr == 0) return EAI_MEMORY; - sin6ptr->sin6_family = AF_INET6; + sin6ptr->sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); ai->ai_addr = reinterpret_cast(sin6ptr); ai->ai_addrlen = sizeof(sockaddr_in6_type); @@ -2378,7 +2627,7 @@ inline int gai_port(addrinfo_type* aihead, int port, int socktype) switch (ai->ai_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): { sockaddr_in4_type* sinptr = reinterpret_cast(ai->ai_addr); @@ -2386,7 +2635,7 @@ inline int gai_port(addrinfo_type* aihead, int port, int socktype) ++num_found; break; } - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): { sockaddr_in6_type* sin6ptr = reinterpret_cast(ai->ai_addr); @@ -2495,10 +2744,10 @@ inline int gai_echeck(const char* host, const char* service, // Check combination of family and socket type. switch (family) { - case AF_UNSPEC: + case BOOST_ASIO_OS_DEF(AF_UNSPEC): break; - case AF_INET: - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET): + case BOOST_ASIO_OS_DEF(AF_INET6): if (service != 0 && service[0] != '\0') if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) return EAI_SOCKTYPE; @@ -2533,18 +2782,18 @@ inline int getaddrinfo_emulation(const char* host, const char* service, // Supply default hints if not specified by caller. addrinfo_type hints = addrinfo_type(); - hints.ai_family = AF_UNSPEC; + hints.ai_family = BOOST_ASIO_OS_DEF(AF_UNSPEC); if (hintsp) hints = *hintsp; // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED // and AI_ALL flags. #if defined(AI_V4MAPPED) - if (hints.ai_family != AF_INET6) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) hints.ai_flags &= ~AI_V4MAPPED; #endif #if defined(AI_ALL) - if (hints.ai_family != AF_INET6) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) hints.ai_flags &= ~AI_ALL; #endif @@ -2564,17 +2813,19 @@ inline int getaddrinfo_emulation(const char* host, const char* service, // Check for IPv4 dotted decimal string. in4_addr_type inaddr; boost::system::error_code ec; - if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1) + if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET), + sptr->host, &inaddr, 0, ec) == 1) { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET)) { freeaddrinfo_emulation(aihead); gai_free(canon); return EAI_FAMILY; } - if (sptr->family == AF_INET) + if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET)) { - rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET); + rc = gai_aistruct(&ainext, &hints, &inaddr, BOOST_ASIO_OS_DEF(AF_INET)); if (rc != 0) { freeaddrinfo_emulation(aihead); @@ -2587,17 +2838,20 @@ inline int getaddrinfo_emulation(const char* host, const char* service, // Check for IPv6 hex string. in6_addr_type in6addr; - if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1) + if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6), + sptr->host, &in6addr, 0, ec) == 1) { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) { freeaddrinfo_emulation(aihead); gai_free(canon); return EAI_FAMILY; } - if (sptr->family == AF_INET6) + if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET6)) { - rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6); + rc = gai_aistruct(&ainext, &hints, &in6addr, + BOOST_ASIO_OS_DEF(AF_INET6)); if (rc != 0) { freeaddrinfo_emulation(aihead); @@ -2634,7 +2888,8 @@ inline int getaddrinfo_emulation(const char* host, const char* service, } // Check for address family mismatch if one was specified. - if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != hptr->h_addrtype) { freeaddrinfo_emulation(aihead); gai_free(canon); @@ -2730,7 +2985,7 @@ inline boost::system::error_code getnameinfo_emulation( unsigned short port; switch (sa->sa_family) { - case AF_INET: + case BOOST_ASIO_OS_DEF(AF_INET): if (salen != sizeof(sockaddr_in4_type)) { return ec = boost::asio::error::invalid_argument; @@ -2740,7 +2995,7 @@ inline boost::system::error_code getnameinfo_emulation( addr_len = sizeof(in4_addr_type); port = reinterpret_cast(sa)->sin_port; break; - case AF_INET6: + case BOOST_ASIO_OS_DEF(AF_INET6): if (salen != sizeof(sockaddr_in6_type)) { return ec = boost::asio::error::invalid_argument; @@ -3055,24 +3310,60 @@ boost::system::error_code background_getnameinfo( return ec; } +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + u_long_type network_to_host_long(u_long_type value) { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + unsigned char* value_p = reinterpret_cast(&value); + u_long_type result = (static_cast(value_p[0]) << 24) + | (static_cast(value_p[1]) << 16) + | (static_cast(value_p[2]) << 8) + | static_cast(value_p[3]); + return result; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) return ntohl(value); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } u_long_type host_to_network_long(u_long_type value) { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + u_long_type result; + unsigned char* result_p = reinterpret_cast(&result); + result_p[0] = static_cast((value >> 24) & 0xFF); + result_p[1] = static_cast((value >> 16) & 0xFF); + result_p[2] = static_cast((value >> 8) & 0xFF); + result_p[3] = static_cast(value & 0xFF); + return result; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) return htonl(value); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } u_short_type network_to_host_short(u_short_type value) { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + unsigned char* value_p = reinterpret_cast(&value); + u_short_type result = (static_cast(value_p[0]) << 8) + | static_cast(value_p[1]); + return result; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) return ntohs(value); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } u_short_type host_to_network_short(u_short_type value) { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + u_long_type result; + unsigned char* result_p = reinterpret_cast(&result); + result_p[0] = static_cast((value >> 8) & 0xFF); + result_p[1] = static_cast(value & 0xFF); + return result; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) return htons(value); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) } } // namespace socket_ops diff --git a/include/boost/asio/detail/impl/socket_select_interrupter.ipp b/include/boost/asio/detail/impl/socket_select_interrupter.ipp index f9ce5fde..c1df8aba 100644 --- a/include/boost/asio/detail/impl/socket_select_interrupter.ipp +++ b/include/boost/asio/detail/impl/socket_select_interrupter.ipp @@ -17,6 +17,8 @@ #include +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) \ || defined(__CYGWIN__) \ || defined(__SYMBIAN32__) @@ -170,4 +172,6 @@ bool socket_select_interrupter::reset() // || defined(__CYGWIN__) // || defined(__SYMBIAN32__) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #endif // BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP diff --git a/include/boost/asio/detail/impl/win_iocp_handle_service.ipp b/include/boost/asio/detail/impl/win_iocp_handle_service.ipp index 604b019d..66d16690 100644 --- a/include/boost/asio/detail/impl/win_iocp_handle_service.ipp +++ b/include/boost/asio/detail/impl/win_iocp_handle_service.ipp @@ -440,14 +440,17 @@ size_t win_iocp_handle_service::do_read( if (!ok) { DWORD last_error = ::GetLastError(); - if (last_error == ERROR_HANDLE_EOF) + if (last_error != ERROR_MORE_DATA) { - ec = boost::asio::error::eof; - } - else - { - ec = boost::system::error_code(last_error, - boost::asio::error::get_system_category()); + if (last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } } return 0; } diff --git a/include/boost/asio/detail/impl/win_iocp_io_service.ipp b/include/boost/asio/detail/impl/win_iocp_io_service.ipp index b63351ef..f0645038 100644 --- a/include/boost/asio/detail/impl/win_iocp_io_service.ipp +++ b/include/boost/asio/detail/impl/win_iocp_io_service.ipp @@ -75,7 +75,8 @@ win_iocp_io_service::win_iocp_io_service( BOOST_ASIO_HANDLER_TRACKING_INIT; iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, - static_cast((std::min)(concurrency_hint, DWORD(~0)))); + static_cast(concurrency_hint < DWORD(~0) + ? concurrency_hint : DWORD(~0))); if (!iocp_.handle) { DWORD last_error = ::GetLastError(); @@ -283,7 +284,8 @@ void win_iocp_io_service::on_pending(win_iocp_operation* op) if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1) { // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op)) + if (!::PostQueuedCompletionStatus(iocp_.handle, + 0, overlapped_contains_result, op)) { // Out of resources. Put on completed queue instead. mutex::scoped_lock lock(dispatch_mutex_); diff --git a/include/boost/asio/detail/impl/winrt_ssocket_service_base.ipp b/include/boost/asio/detail/impl/winrt_ssocket_service_base.ipp new file mode 100644 index 00000000..041bad73 --- /dev/null +++ b/include/boost/asio/detail/impl/winrt_ssocket_service_base.ipp @@ -0,0 +1,614 @@ +// +// detail/impl/winrt_ssocket_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP +#define BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +winrt_ssocket_service_base::winrt_ssocket_service_base( + boost::asio::io_service& io_service) + : io_service_(use_service(io_service)), + async_manager_(use_service(io_service)), + mutex_(), + impl_list_(0) +{ +} + +void winrt_ssocket_service_base::shutdown_service() +{ + // Close all implementations, causing all operations to complete. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + base_implementation_type* impl = impl_list_; + while (impl) + { + boost::system::error_code ignored_ec; + close(*impl, ignored_ec); + impl = impl->next_; + } +} + +void winrt_ssocket_service_base::construct( + winrt_ssocket_service_base::base_implementation_type& impl) +{ + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; +} + +void winrt_ssocket_service_base::base_move_construct( + winrt_ssocket_service_base::base_implementation_type& impl, + winrt_ssocket_service_base::base_implementation_type& other_impl) +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = nullptr; + + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; +} + +void winrt_ssocket_service_base::base_move_assign( + winrt_ssocket_service_base::base_implementation_type& impl, + winrt_ssocket_service_base& other_service, + winrt_ssocket_service_base::base_implementation_type& other_impl) +{ + boost::system::error_code ignored_ec; + close(impl, ignored_ec); + + if (this != &other_service) + { + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = nullptr; + + if (this != &other_service) + { + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(other_service.mutex_); + impl.next_ = other_service.impl_list_; + impl.prev_ = 0; + if (other_service.impl_list_) + other_service.impl_list_->prev_ = &impl; + other_service.impl_list_ = &impl; + } +} + +void winrt_ssocket_service_base::destroy( + winrt_ssocket_service_base::base_implementation_type& impl) +{ + boost::system::error_code ignored_ec; + close(impl, ignored_ec); + + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; +} + +boost::system::error_code winrt_ssocket_service_base::close( + winrt_ssocket_service_base::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (impl.socket_) + { + delete impl.socket_; + impl.socket_ = nullptr; + } + + ec = boost::system::error_code(); + return ec; +} + +std::size_t winrt_ssocket_service_base::do_get_endpoint( + const base_implementation_type& impl, bool local, + void* addr, std::size_t addr_len, boost::system::error_code& ec) const +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return addr_len; + } + + try + { + std::string addr_string = winrt_utils::string(local + ? impl.socket_->Information->LocalAddress->CanonicalName + : impl.socket_->Information->RemoteAddress->CanonicalName); + unsigned short port = winrt_utils::integer(local + ? impl.socket_->Information->LocalPort + : impl.socket_->Information->RemotePort); + unsigned long scope = 0; + + switch (reinterpret_cast(addr)->sa_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + if (addr_len < sizeof(sockaddr_in4_type)) + { + ec = boost::asio::error::invalid_argument; + return addr_len; + } + else + { + socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET), addr_string.c_str(), + &reinterpret_cast(addr)->sin_addr, &scope, ec); + reinterpret_cast(addr)->sin_port + = socket_ops::host_to_network_short(port); + ec = boost::system::error_code(); + return sizeof(sockaddr_in4_type); + } + case BOOST_ASIO_OS_DEF(AF_INET6): + if (addr_len < sizeof(sockaddr_in6_type)) + { + ec = boost::asio::error::invalid_argument; + return addr_len; + } + else + { + socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6), addr_string.c_str(), + &reinterpret_cast(addr)->sin6_addr, &scope, ec); + reinterpret_cast(addr)->sin6_port + = socket_ops::host_to_network_short(port); + ec = boost::system::error_code(); + return sizeof(sockaddr_in6_type); + } + default: + ec = boost::asio::error::address_family_not_supported; + return addr_len; + } + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return addr_len; + } +} + +boost::system::error_code winrt_ssocket_service_base::do_set_option( + winrt_ssocket_service_base::base_implementation_type& impl, + int level, int optname, const void* optval, + std::size_t optlen, boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + try + { + if (level == BOOST_ASIO_OS_DEF(SOL_SOCKET) + && optname == BOOST_ASIO_OS_DEF(SO_KEEPALIVE)) + { + if (optlen == sizeof(int)) + { + int value = 0; + std::memcpy(&value, optval, optlen); + impl.socket_->Control->KeepAlive = !!value; + ec = boost::system::error_code(); + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + else if (level == BOOST_ASIO_OS_DEF(IPPROTO_TCP) + && optname == BOOST_ASIO_OS_DEF(TCP_NODELAY)) + { + if (optlen == sizeof(int)) + { + int value = 0; + std::memcpy(&value, optval, optlen); + impl.socket_->Control->NoDelay = !!value; + ec = boost::system::error_code(); + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + } + + return ec; +} + +void winrt_ssocket_service_base::do_get_option( + const winrt_ssocket_service_base::base_implementation_type& impl, + int level, int optname, void* optval, + std::size_t* optlen, boost::system::error_code& ec) const +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return; + } + + try + { + if (level == BOOST_ASIO_OS_DEF(SOL_SOCKET) + && optname == BOOST_ASIO_OS_DEF(SO_KEEPALIVE)) + { + if (*optlen >= sizeof(int)) + { + int value = impl.socket_->Control->KeepAlive ? 1 : 0; + std::memcpy(optval, &value, sizeof(int)); + *optlen = sizeof(int); + ec = boost::system::error_code(); + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + else if (level == BOOST_ASIO_OS_DEF(IPPROTO_TCP) + && optname == BOOST_ASIO_OS_DEF(TCP_NODELAY)) + { + if (*optlen >= sizeof(int)) + { + int value = impl.socket_->Control->NoDelay ? 1 : 0; + std::memcpy(optval, &value, sizeof(int)); + *optlen = sizeof(int); + ec = boost::system::error_code(); + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + else + { + ec = boost::asio::error::invalid_argument; + } + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + } +} + +boost::system::error_code winrt_ssocket_service_base::do_connect( + winrt_ssocket_service_base::base_implementation_type& impl, + const void* addr, boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + char addr_string[max_addr_v6_str_len]; + unsigned short port; + switch (reinterpret_cast(addr)->sa_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET), + &reinterpret_cast(addr)->sin_addr, + addr_string, sizeof(addr_string), 0, ec); + port = socket_ops::network_to_host_short( + reinterpret_cast(addr)->sin_port); + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET6), + &reinterpret_cast(addr)->sin6_addr, + addr_string, sizeof(addr_string), 0, ec); + port = socket_ops::network_to_host_short( + reinterpret_cast(addr)->sin6_port); + break; + default: + ec = boost::asio::error::address_family_not_supported; + return ec; + } + + if (!ec) try + { + async_manager_.sync(impl.socket_->ConnectAsync( + ref new Windows::Networking::HostName( + winrt_utils::string(addr_string)), + winrt_utils::string(port)), ec); + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + } + + return ec; +} + +void winrt_ssocket_service_base::start_connect_op( + winrt_ssocket_service_base::base_implementation_type& impl, + const void* addr, winrt_async_op* op, bool is_continuation) +{ + if (!is_open(impl)) + { + op->ec_ = boost::asio::error::bad_descriptor; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + char addr_string[max_addr_v6_str_len]; + unsigned short port = 0; + switch (reinterpret_cast(addr)->sa_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET), + &reinterpret_cast(addr)->sin_addr, + addr_string, sizeof(addr_string), 0, op->ec_); + port = socket_ops::network_to_host_short( + reinterpret_cast(addr)->sin_port); + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET6), + &reinterpret_cast(addr)->sin6_addr, + addr_string, sizeof(addr_string), 0, op->ec_); + port = socket_ops::network_to_host_short( + reinterpret_cast(addr)->sin6_port); + break; + default: + op->ec_ = boost::asio::error::address_family_not_supported; + break; + } + + if (op->ec_) + { + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + try + { + async_manager_.async(impl.socket_->ConnectAsync( + ref new Windows::Networking::HostName( + winrt_utils::string(addr_string)), + winrt_utils::string(port)), op); + } + catch (Platform::Exception^ e) + { + op->ec_ = boost::system::error_code( + e->HResult, boost::system::system_category()); + io_service_.post_immediate_completion(op, is_continuation); + } +} + +std::size_t winrt_ssocket_service_base::do_send( + winrt_ssocket_service_base::base_implementation_type& impl, + const boost::asio::const_buffer& data, + socket_base::message_flags flags, boost::system::error_code& ec) +{ + if (flags) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + try + { + buffer_sequence_adapter bufs(boost::asio::buffer(data)); + + if (bufs.all_empty()) + { + ec = boost::system::error_code(); + return 0; + } + + return async_manager_.sync( + impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), ec); + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return 0; + } +} + +void winrt_ssocket_service_base::start_send_op( + winrt_ssocket_service_base::base_implementation_type& impl, + const boost::asio::const_buffer& data, socket_base::message_flags flags, + winrt_async_op* op, bool is_continuation) +{ + if (flags) + { + op->ec_ = boost::asio::error::operation_not_supported; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + if (!is_open(impl)) + { + op->ec_ = boost::asio::error::bad_descriptor; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + try + { + buffer_sequence_adapter bufs(boost::asio::buffer(data)); + + if (bufs.all_empty()) + { + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + async_manager_.async( + impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), op); + } + catch (Platform::Exception^ e) + { + op->ec_ = boost::system::error_code(e->HResult, + boost::system::system_category()); + io_service_.post_immediate_completion(op, is_continuation); + } +} + +std::size_t winrt_ssocket_service_base::do_receive( + winrt_ssocket_service_base::base_implementation_type& impl, + const boost::asio::mutable_buffer& data, + socket_base::message_flags flags, boost::system::error_code& ec) +{ + if (flags) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + try + { + buffer_sequence_adapter bufs(boost::asio::buffer(data)); + + if (bufs.all_empty()) + { + ec = boost::system::error_code(); + return 0; + } + + async_manager_.sync( + impl.socket_->InputStream->ReadAsync( + bufs.buffers()[0], bufs.buffers()[0]->Capacity, + Windows::Storage::Streams::InputStreamOptions::Partial), ec); + + std::size_t bytes_transferred = bufs.buffers()[0]->Length; + if (bytes_transferred == 0 && !ec) + { + ec = boost::asio::error::eof; + } + + return bytes_transferred; + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return 0; + } +} + +void winrt_ssocket_service_base::start_receive_op( + winrt_ssocket_service_base::base_implementation_type& impl, + const boost::asio::mutable_buffer& data, socket_base::message_flags flags, + winrt_async_op* op, + bool is_continuation) +{ + if (flags) + { + op->ec_ = boost::asio::error::operation_not_supported; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + if (!is_open(impl)) + { + op->ec_ = boost::asio::error::bad_descriptor; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + try + { + buffer_sequence_adapter bufs(boost::asio::buffer(data)); + + if (bufs.all_empty()) + { + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + async_manager_.async( + impl.socket_->InputStream->ReadAsync( + bufs.buffers()[0], bufs.buffers()[0]->Capacity, + Windows::Storage::Streams::InputStreamOptions::Partial), op); + } + catch (Platform::Exception^ e) + { + op->ec_ = boost::system::error_code(e->HResult, + boost::system::system_category()); + io_service_.post_immediate_completion(op, is_continuation); + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP diff --git a/include/boost/asio/detail/impl/winrt_timer_scheduler.hpp b/include/boost/asio/detail/impl/winrt_timer_scheduler.hpp new file mode 100644 index 00000000..ef753e80 --- /dev/null +++ b/include/boost/asio/detail/impl/winrt_timer_scheduler.hpp @@ -0,0 +1,81 @@ +// +// detail/impl/winrt_timer_scheduler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_HPP +#define BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +void winrt_timer_scheduler::add_timer_queue(timer_queue& queue) +{ + do_add_timer_queue(queue); +} + +// Remove a timer queue from the reactor. +template +void winrt_timer_scheduler::remove_timer_queue(timer_queue& queue) +{ + do_remove_timer_queue(queue); +} + +template +void winrt_timer_scheduler::schedule_timer(timer_queue& queue, + const typename Time_Traits::time_type& time, + typename timer_queue::per_timer_data& timer, wait_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + event_.signal(lock); +} + +template +std::size_t winrt_timer_scheduler::cancel_timer(timer_queue& queue, + typename timer_queue::per_timer_data& timer, + std::size_t max_cancelled) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + op_queue ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_HPP diff --git a/include/boost/asio/detail/impl/winrt_timer_scheduler.ipp b/include/boost/asio/detail/impl/winrt_timer_scheduler.ipp new file mode 100644 index 00000000..a57c65b6 --- /dev/null +++ b/include/boost/asio/detail/impl/winrt_timer_scheduler.ipp @@ -0,0 +1,124 @@ +// +// detail/impl/winrt_timer_scheduler.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP +#define BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +winrt_timer_scheduler::winrt_timer_scheduler( + boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + io_service_(use_service(io_service)), + mutex_(), + event_(), + timer_queues_(), + thread_(0), + stop_thread_(false), + shutdown_(false) +{ + thread_ = new boost::asio::detail::thread( + bind_handler(&winrt_timer_scheduler::call_run_thread, this)); +} + +winrt_timer_scheduler::~winrt_timer_scheduler() +{ + shutdown_service(); +} + +void winrt_timer_scheduler::shutdown_service() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + stop_thread_ = true; + event_.signal(lock); + lock.unlock(); + + if (thread_) + { + thread_->join(); + delete thread_; + thread_ = 0; + } + + op_queue ops; + timer_queues_.get_all_timers(ops); + io_service_.abandon_operations(ops); +} + +void winrt_timer_scheduler::fork_service(boost::asio::io_service::fork_event) +{ +} + +void winrt_timer_scheduler::init_task() +{ +} + +void winrt_timer_scheduler::run_thread() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + const long max_wait_duration = 5 * 60 * 1000000; + long wait_duration = timer_queues_.wait_duration_usec(max_wait_duration); + event_.wait_for_usec(lock, wait_duration); + event_.clear(lock); + op_queue ops; + timer_queues_.get_ready_timers(ops); + if (!ops.empty()) + { + lock.unlock(); + io_service_.post_deferred_completions(ops); + lock.lock(); + } + } +} + +void winrt_timer_scheduler::call_run_thread(winrt_timer_scheduler* scheduler) +{ + scheduler->run_thread(); +} + +void winrt_timer_scheduler::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void winrt_timer_scheduler::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP diff --git a/include/boost/asio/detail/io_control.hpp b/include/boost/asio/detail/io_control.hpp index f35468b1..a1f96e12 100644 --- a/include/boost/asio/detail/io_control.hpp +++ b/include/boost/asio/detail/io_control.hpp @@ -45,7 +45,7 @@ public: // Get the name of the IO control command. int name() const { - return static_cast(FIONBIO); + return static_cast(BOOST_ASIO_OS_DEF(FIONBIO)); } // Set the value of the I/O control command. @@ -95,7 +95,7 @@ public: // Get the name of the IO control command. int name() const { - return static_cast(FIONREAD); + return static_cast(BOOST_ASIO_OS_DEF(FIONREAD)); } // Set the value of the I/O control command. diff --git a/include/boost/asio/detail/keyword_tss_ptr.hpp b/include/boost/asio/detail/keyword_tss_ptr.hpp index bdd76624..5dffa8f1 100644 --- a/include/boost/asio/detail/keyword_tss_ptr.hpp +++ b/include/boost/asio/detail/keyword_tss_ptr.hpp @@ -55,11 +55,11 @@ public: } private: - static __thread T* value_; + static BOOST_ASIO_THREAD_KEYWORD T* value_; }; template -__thread T* keyword_tss_ptr::value_; +BOOST_ASIO_THREAD_KEYWORD T* keyword_tss_ptr::value_; } // namespace detail } // namespace asio diff --git a/include/boost/asio/detail/kqueue_reactor.hpp b/include/boost/asio/detail/kqueue_reactor.hpp index 16669c23..baf01452 100644 --- a/include/boost/asio/detail/kqueue_reactor.hpp +++ b/include/boost/asio/detail/kqueue_reactor.hpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/asio/detail/kqueue_reactor_fwd.hpp b/include/boost/asio/detail/kqueue_reactor_fwd.hpp deleted file mode 100644 index bd1dfc0f..00000000 --- a/include/boost/asio/detail/kqueue_reactor_fwd.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// detail/kqueue_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP -#define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include - -#if defined(BOOST_ASIO_HAS_KQUEUE) - -namespace boost { -namespace asio { -namespace detail { - -class kqueue_reactor; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // defined(BOOST_ASIO_HAS_KQUEUE) - -#endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP diff --git a/include/boost/asio/detail/mutex.hpp b/include/boost/asio/detail/mutex.hpp index 03bc3f82..5898af72 100644 --- a/include/boost/asio/detail/mutex.hpp +++ b/include/boost/asio/detail/mutex.hpp @@ -23,8 +23,10 @@ # include #elif defined(BOOST_ASIO_HAS_PTHREADS) # include +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# include #else -# error Only Windows and POSIX are supported! +# error Only Windows, POSIX and std::mutex are supported! #endif namespace boost { @@ -37,6 +39,8 @@ typedef null_mutex mutex; typedef win_mutex mutex; #elif defined(BOOST_ASIO_HAS_PTHREADS) typedef posix_mutex mutex; +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +typedef std_mutex mutex; #endif } // namespace detail diff --git a/include/boost/asio/detail/null_reactor.hpp b/include/boost/asio/detail/null_reactor.hpp new file mode 100644 index 00000000..acd70296 --- /dev/null +++ b/include/boost/asio/detail/null_reactor.hpp @@ -0,0 +1,69 @@ +// +// detail/null_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_NULL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class null_reactor + : public boost::asio::detail::service_base +{ +public: + // Constructor. + null_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service) + { + } + + // Destructor. + ~null_reactor() + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // No-op because should never be called. + void run(bool /*block*/, op_queue& /*ops*/) + { + } + + // No-op. + void interrupt() + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_NULL_REACTOR_HPP diff --git a/include/boost/asio/detail/null_signal_blocker.hpp b/include/boost/asio/detail/null_signal_blocker.hpp index c3865241..d69f49e4 100644 --- a/include/boost/asio/detail/null_signal_blocker.hpp +++ b/include/boost/asio/detail/null_signal_blocker.hpp @@ -19,6 +19,7 @@ #if !defined(BOOST_ASIO_HAS_THREADS) \ || defined(BOOST_ASIO_WINDOWS) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) \ || defined(__CYGWIN__) \ || defined(__SYMBIAN32__) @@ -63,6 +64,7 @@ public: #endif // !defined(BOOST_ASIO_HAS_THREADS) // || defined(BOOST_ASIO_WINDOWS) + // || defined(BOOST_ASIO_WINDOWS_RUNTIME) // || defined(__CYGWIN__) // || defined(__SYMBIAN32__) diff --git a/include/boost/asio/detail/null_socket_service.hpp b/include/boost/asio/detail/null_socket_service.hpp new file mode 100644 index 00000000..196baf37 --- /dev/null +++ b/include/boost/asio/detail/null_socket_service.hpp @@ -0,0 +1,499 @@ +// +// detail/null_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_SOCKET_SERVICE_HPP +#define BOOST_ASIO_DETAIL_NULL_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class null_socket_service +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef int native_handle_type; + + // The implementation type of the socket. + struct implementation_type + { + }; + + // Constructor. + null_socket_service(boost::asio::io_service& io_service) + : io_service_(io_service) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new socket implementation. + void construct(implementation_type&) + { + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type&, implementation_type&) + { + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type&, + null_socket_service&, implementation_type&) + { + } + + // Move-construct a new socket implementation from another protocol type. + template + void converting_move_construct(implementation_type&, + typename null_socket_service::implementation_type&) + { + } + + // Destroy a socket implementation. + void destroy(implementation_type&) + { + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type&, + const protocol_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type&, const protocol_type&, + const native_handle_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Determine whether the socket is open. + bool is_open(const implementation_type&) const + { + return false; + } + + // Destroy a socket implementation. + boost::system::error_code close(implementation_type&, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Get the native socket representation. + native_handle_type native_handle(implementation_type&) + { + return 0; + } + + // Cancel all operations associated with the socket. + boost::system::error_code cancel(implementation_type&, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return false; + } + + // Determine the number of bytes available for reading. + std::size_t available(const implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Place the socket into the state where it will listen for new connections. + boost::system::error_code listen(implementation_type&, + int, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type&, + IO_Control_Command&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const implementation_type&) const + { + return false; + } + + // Sets the non-blocking mode of the socket. + boost::system::error_code non_blocking(implementation_type&, + bool, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const implementation_type&) const + { + return false; + } + + // Sets the non-blocking mode of the native socket implementation. + boost::system::error_code native_non_blocking(implementation_type&, + bool, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type&, + socket_base::shutdown_type, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type&, + const endpoint_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type&, + const Option&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Set a socket option. + template + boost::system::error_code get_option(const implementation_type&, + Option&, boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return endpoint_type(); + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return endpoint_type(); + } + + // Send the given data to the peer. + template + std::size_t send(implementation_type&, const ConstBufferSequence&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Wait until data can be sent without blocking. + std::size_t send(implementation_type&, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(implementation_type&, const ConstBufferSequence&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type&, const null_buffers&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Receive some data from the peer. Returns the number of bytes received. + template + std::size_t receive(implementation_type&, const MutableBufferSequence&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Wait until data can be received without blocking. + std::size_t receive(implementation_type&, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(implementation_type&, const MutableBufferSequence&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Wait until data can be received without blocking. + template + void async_receive(implementation_type&, const null_buffers&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Receive some data with associated flags. Returns the number of bytes + // received. + template + std::size_t receive_with_flags(implementation_type&, + const MutableBufferSequence&, socket_base::message_flags, + socket_base::message_flags&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Wait until data can be received without blocking. + std::size_t receive_with_flags(implementation_type&, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive_with_flags(implementation_type&, + const MutableBufferSequence&, socket_base::message_flags, + socket_base::message_flags&, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Wait until data can be received without blocking. + template + void async_receive_with_flags(implementation_type&, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags&, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template + std::size_t send_to(implementation_type&, const ConstBufferSequence&, + const endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Wait until data can be sent without blocking. + std::size_t send_to(implementation_type&, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send_to(implementation_type&, const ConstBufferSequence&, + const endpoint_type&, socket_base::message_flags, + Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type&, const null_buffers&, + const endpoint_type&, socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template + std::size_t receive_from(implementation_type&, const MutableBufferSequence&, + endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Wait until data can be received without blocking. + std::size_t receive_from(implementation_type&, const null_buffers&, + endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template + void async_receive_from(implementation_type&, + const MutableBufferSequence&, endpoint_type&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type&, + const null_buffers&, endpoint_type&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.post(detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Accept a new connection. + template + boost::system::error_code accept(implementation_type&, + Socket&, endpoint_type*, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Start an asynchronous accept. The peer and peer_endpoint objects + // must be valid until the accept's handler is invoked. + template + void async_accept(implementation_type&, Socket&, + endpoint_type*, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + io_service_.post(detail::bind_handler(handler, ec)); + } + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type&, + const endpoint_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Start an asynchronous connect. + template + void async_connect(implementation_type&, + const endpoint_type&, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + io_service_.post(detail::bind_handler(handler, ec)); + } + +private: + boost::asio::io_service& io_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_NULL_SOCKET_SERVICE_HPP diff --git a/include/boost/asio/detail/pipe_select_interrupter.hpp b/include/boost/asio/detail/pipe_select_interrupter.hpp index 8394ff73..3c659d4d 100644 --- a/include/boost/asio/detail/pipe_select_interrupter.hpp +++ b/include/boost/asio/detail/pipe_select_interrupter.hpp @@ -18,6 +18,7 @@ #include #if !defined(BOOST_ASIO_WINDOWS) +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if !defined(__CYGWIN__) #if !defined(__SYMBIAN32__) #if !defined(BOOST_ASIO_HAS_EVENTFD) @@ -84,6 +85,7 @@ private: #endif // !defined(BOOST_ASIO_HAS_EVENTFD) #endif // !defined(__SYMBIAN32__) #endif // !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // !defined(BOOST_ASIO_WINDOWS) #endif // BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/include/boost/asio/detail/pop_options.hpp b/include/boost/asio/detail/pop_options.hpp index 2b873884..faa9a916 100644 --- a/include/boost/asio/detail/pop_options.hpp +++ b/include/boost/asio/detail/pop_options.hpp @@ -95,4 +95,11 @@ # pragma warning (pop) # pragma pack (pop) +# if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# if defined(BOOST_ASIO_CLR_WORKAROUND) +# undef generic +# undef BOOST_ASIO_CLR_WORKAROUND +# endif +# endif + #endif diff --git a/include/boost/asio/detail/posix_fd_set_adapter.hpp b/include/boost/asio/detail/posix_fd_set_adapter.hpp index fa57edd4..3dbb0673 100644 --- a/include/boost/asio/detail/posix_fd_set_adapter.hpp +++ b/include/boost/asio/detail/posix_fd_set_adapter.hpp @@ -17,7 +17,9 @@ #include -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(__CYGWIN__) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #include #include @@ -84,6 +86,8 @@ private: #include -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(__CYGWIN__) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP diff --git a/include/boost/asio/detail/posix_tss_ptr.hpp b/include/boost/asio/detail/posix_tss_ptr.hpp index 6ec748d7..40fa5145 100644 --- a/include/boost/asio/detail/posix_tss_ptr.hpp +++ b/include/boost/asio/detail/posix_tss_ptr.hpp @@ -64,7 +64,6 @@ private: // Thread-specific storage to allow unlocked access to determine whether a // thread is a member of the pool. pthread_key_t tss_key_; - }; } // namespace detail diff --git a/include/boost/asio/detail/push_options.hpp b/include/boost/asio/detail/push_options.hpp index eec86f78..573a3334 100644 --- a/include/boost/asio/detail/push_options.hpp +++ b/include/boost/asio/detail/push_options.hpp @@ -103,7 +103,9 @@ # pragma warning (disable:4180) # pragma warning (disable:4244) # pragma warning (disable:4355) +# pragma warning (disable:4510) # pragma warning (disable:4512) +# pragma warning (disable:4610) # pragma warning (disable:4675) # if defined(_M_IX86) && defined(_Wp64) // The /Wp64 option is broken. If you want to check 64 bit portability, use a @@ -124,4 +126,13 @@ # error Multithreaded RTL must be selected. # endif // !defined(_MT) +# if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# if !defined(BOOST_ASIO_DISABLE_CLR_WORKAROUND) +# if !defined(generic) +# define generic cpp_generic +# define BOOST_ASIO_CLR_WORKAROUND +# endif +# endif +# endif + #endif diff --git a/include/boost/asio/detail/reactive_descriptor_service.hpp b/include/boost/asio/detail/reactive_descriptor_service.hpp index 134fcbb7..3d7ed24c 100644 --- a/include/boost/asio/detail/reactive_descriptor_service.hpp +++ b/include/boost/asio/detail/reactive_descriptor_service.hpp @@ -17,7 +17,9 @@ #include -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) #include #include @@ -315,6 +317,8 @@ private: # include #endif // defined(BOOST_ASIO_HEADER_ONLY) -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) #endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/include/boost/asio/detail/reactive_socket_accept_op.hpp b/include/boost/asio/detail/reactive_socket_accept_op.hpp index 75f9f641..d4f7ab83 100644 --- a/include/boost/asio/detail/reactive_socket_accept_op.hpp +++ b/include/boost/asio/detail/reactive_socket_accept_op.hpp @@ -58,7 +58,7 @@ public: o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket); // On success, assign new connection to peer socket object. - if (new_socket >= 0) + if (new_socket != invalid_socket) { socket_holder new_socket_holder(new_socket); if (o->peer_endpoint_) diff --git a/include/boost/asio/detail/reactive_socket_connect_op.hpp b/include/boost/asio/detail/reactive_socket_connect_op.hpp index a603f26c..5958569c 100644 --- a/include/boost/asio/detail/reactive_socket_connect_op.hpp +++ b/include/boost/asio/detail/reactive_socket_connect_op.hpp @@ -29,15 +29,12 @@ namespace boost { namespace asio { namespace detail { -template class reactive_socket_connect_op_base : public reactor_op { public: - reactive_socket_connect_op_base(socket_type socket, - const typename Protocol::endpoint& peer_endpoint, func_type complete_func) + reactive_socket_connect_op_base(socket_type socket, func_type complete_func) : reactor_op(&reactive_socket_connect_op_base::do_perform, complete_func), - socket_(socket), - peer_endpoint_(peer_endpoint) + socket_(socket) { } @@ -46,25 +43,21 @@ public: reactive_socket_connect_op_base* o( static_cast(base)); - return socket_ops::non_blocking_connect(o->socket_, - o->peer_endpoint_.data(), o->peer_endpoint_.size(), o->ec_); + return socket_ops::non_blocking_connect(o->socket_, o->ec_); } private: socket_type socket_; - typename Protocol::endpoint peer_endpoint_; }; -template -class reactive_socket_connect_op : - public reactive_socket_connect_op_base +template +class reactive_socket_connect_op : public reactive_socket_connect_op_base { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); - reactive_socket_connect_op(socket_type socket, - const typename Protocol::endpoint& peer_endpoint, Handler& handler) - : reactive_socket_connect_op_base(socket, peer_endpoint, + reactive_socket_connect_op(socket_type socket, Handler& handler) + : reactive_socket_connect_op_base(socket, &reactive_socket_connect_op::do_complete), handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) { diff --git a/include/boost/asio/detail/reactive_socket_service.hpp b/include/boost/asio/detail/reactive_socket_service.hpp index e9027086..205e15ef 100644 --- a/include/boost/asio/detail/reactive_socket_service.hpp +++ b/include/boost/asio/detail/reactive_socket_service.hpp @@ -434,11 +434,11 @@ public: boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_connect_op op; + typedef reactive_socket_connect_op op; typename op::ptr p = { boost::asio::detail::addressof(handler), boost_asio_handler_alloc_helpers::allocate( sizeof(op), handler), 0 }; - p.p = new (p.v) op(impl.socket_, peer_endpoint, handler); + p.p = new (p.v) op(impl.socket_, handler); BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect")); diff --git a/include/boost/asio/detail/reactive_socket_service_base.hpp b/include/boost/asio/detail/reactive_socket_service_base.hpp index 52042431..3a84bd36 100644 --- a/include/boost/asio/detail/reactive_socket_service_base.hpp +++ b/include/boost/asio/detail/reactive_socket_service_base.hpp @@ -17,7 +17,8 @@ #include -#if !defined(BOOST_ASIO_HAS_IOCP) +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #include #include @@ -198,7 +199,7 @@ public: template void async_send(base_implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -222,7 +223,7 @@ public: // Start an asynchronous wait until data can be sent without blocking. template void async_send(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler handler) + socket_base::message_flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -269,7 +270,7 @@ public: template void async_receive(base_implementation_type& impl, const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -297,7 +298,7 @@ public: // Wait until data can be received without blocking. template void async_receive(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -354,7 +355,7 @@ public: template void async_receive_with_flags(base_implementation_type& impl, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler handler) + socket_base::message_flags& out_flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -381,7 +382,7 @@ public: template void async_receive_with_flags(base_implementation_type& impl, const null_buffers&, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler handler) + socket_base::message_flags& out_flags, Handler& handler) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); @@ -446,5 +447,6 @@ protected: #endif // defined(BOOST_ASIO_HEADER_ONLY) #endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP diff --git a/include/boost/asio/detail/reactor.hpp b/include/boost/asio/detail/reactor.hpp index 29f51dc2..e45f30ab 100644 --- a/include/boost/asio/detail/reactor.hpp +++ b/include/boost/asio/detail/reactor.hpp @@ -23,6 +23,8 @@ # include #elif defined(BOOST_ASIO_HAS_DEV_POLL) # include +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include #else # include #endif diff --git a/include/boost/asio/detail/reactor_fwd.hpp b/include/boost/asio/detail/reactor_fwd.hpp index 58c86aaa..6bc2e1dc 100644 --- a/include/boost/asio/detail/reactor_fwd.hpp +++ b/include/boost/asio/detail/reactor_fwd.hpp @@ -17,32 +17,22 @@ #include -#if defined(BOOST_ASIO_HAS_IOCP) -# include -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include -#else -# include -#endif - namespace boost { namespace asio { namespace detail { -#if defined(BOOST_ASIO_HAS_IOCP) -typedef select_reactor reactor; +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +typedef class null_reactor reactor; +#elif defined(BOOST_ASIO_HAS_IOCP) +typedef class select_reactor reactor; #elif defined(BOOST_ASIO_HAS_EPOLL) -typedef epoll_reactor reactor; +typedef class epoll_reactor reactor; #elif defined(BOOST_ASIO_HAS_KQUEUE) -typedef kqueue_reactor reactor; +typedef class kqueue_reactor reactor; #elif defined(BOOST_ASIO_HAS_DEV_POLL) -typedef dev_poll_reactor reactor; +typedef class dev_poll_reactor reactor; #else -typedef select_reactor reactor; +typedef class select_reactor reactor; #endif } // namespace detail diff --git a/include/boost/asio/detail/resolver_service.hpp b/include/boost/asio/detail/resolver_service.hpp index f4f3907c..f855405b 100644 --- a/include/boost/asio/detail/resolver_service.hpp +++ b/include/boost/asio/detail/resolver_service.hpp @@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #include #include #include @@ -123,4 +126,6 @@ public: #include +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #endif // BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP diff --git a/include/boost/asio/detail/resolver_service_base.hpp b/include/boost/asio/detail/resolver_service_base.hpp index f618026e..42e246e4 100644 --- a/include/boost/asio/detail/resolver_service_base.hpp +++ b/include/boost/asio/detail/resolver_service_base.hpp @@ -65,6 +65,7 @@ protected: // Helper function to start an asynchronous resolve operation. BOOST_ASIO_DECL void start_resolve_op(operation* op); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) // Helper class to perform exception-safe cleanup of addrinfo objects. class auto_addrinfo : private boost::asio::detail::noncopyable @@ -89,6 +90,7 @@ protected: private: boost::asio::detail::addrinfo_type* ai_; }; +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) // Helper class to run the work io_service in a thread. class work_io_service_runner; diff --git a/include/boost/asio/detail/select_interrupter.hpp b/include/boost/asio/detail/select_interrupter.hpp index 65caa097..8cab4dc4 100644 --- a/include/boost/asio/detail/select_interrupter.hpp +++ b/include/boost/asio/detail/select_interrupter.hpp @@ -17,6 +17,8 @@ #include +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__) # include #elif defined(BOOST_ASIO_HAS_EVENTFD) @@ -41,4 +43,6 @@ typedef pipe_select_interrupter select_interrupter; } // namespace asio } // namespace boost +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #endif // BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/include/boost/asio/detail/select_reactor.hpp b/include/boost/asio/detail/select_reactor.hpp index f5907694..74deab24 100644 --- a/include/boost/asio/detail/select_reactor.hpp +++ b/include/boost/asio/detail/select_reactor.hpp @@ -20,7 +20,8 @@ #if defined(BOOST_ASIO_HAS_IOCP) \ || (!defined(BOOST_ASIO_HAS_DEV_POLL) \ && !defined(BOOST_ASIO_HAS_EPOLL) \ - && !defined(BOOST_ASIO_HAS_KQUEUE)) + && !defined(BOOST_ASIO_HAS_KQUEUE) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #include #include @@ -30,10 +31,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -216,6 +215,7 @@ private: #endif // defined(BOOST_ASIO_HAS_IOCP) // || (!defined(BOOST_ASIO_HAS_DEV_POLL) // && !defined(BOOST_ASIO_HAS_EPOLL) - // && !defined(BOOST_ASIO_HAS_KQUEUE)) + // && !defined(BOOST_ASIO_HAS_KQUEUE) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) #endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP diff --git a/include/boost/asio/detail/select_reactor_fwd.hpp b/include/boost/asio/detail/select_reactor_fwd.hpp deleted file mode 100644 index f5a7a0ca..00000000 --- a/include/boost/asio/detail/select_reactor_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// detail/select_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP -#define BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -namespace boost { -namespace asio { -namespace detail { - -class select_reactor; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP diff --git a/include/boost/asio/detail/service_registry_fwd.hpp b/include/boost/asio/detail/service_registry_fwd.hpp deleted file mode 100644 index 8304cd0f..00000000 --- a/include/boost/asio/detail/service_registry_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// detail/service_registry_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP -#define BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -namespace boost { -namespace asio { -namespace detail { - -class service_registry; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP diff --git a/include/boost/asio/detail/signal_blocker.hpp b/include/boost/asio/detail/signal_blocker.hpp index 559ef139..4bb6813d 100644 --- a/include/boost/asio/detail/signal_blocker.hpp +++ b/include/boost/asio/detail/signal_blocker.hpp @@ -18,6 +18,7 @@ #include #if !defined(BOOST_ASIO_HAS_THREADS) || defined(BOOST_ASIO_WINDOWS) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) \ || defined(__CYGWIN__) || defined(__SYMBIAN32__) # include #elif defined(BOOST_ASIO_HAS_PTHREADS) @@ -31,6 +32,7 @@ namespace asio { namespace detail { #if !defined(BOOST_ASIO_HAS_THREADS) || defined(BOOST_ASIO_WINDOWS) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) \ || defined(__CYGWIN__) || defined(__SYMBIAN32__) typedef null_signal_blocker signal_blocker; #elif defined(BOOST_ASIO_HAS_PTHREADS) diff --git a/include/boost/asio/detail/signal_set_service.hpp b/include/boost/asio/detail/signal_set_service.hpp index c833057c..a3ddcbb2 100644 --- a/include/boost/asio/detail/signal_set_service.hpp +++ b/include/boost/asio/detail/signal_set_service.hpp @@ -46,7 +46,7 @@ enum { max_signal_number = 128 }; extern BOOST_ASIO_DECL struct signal_state* get_signal_state(); -extern "C" BOOST_ASIO_DECL void asio_signal_handler(int signal_number); +extern "C" BOOST_ASIO_DECL void boost_asio_signal_handler(int signal_number); class signal_set_service { @@ -182,7 +182,9 @@ private: // The io_service instance used for dispatching handlers. io_service_impl& io_service_; -#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) // The type used for registering for pipe reactor notifications. class pipe_read_op; @@ -191,7 +193,9 @@ private: // The per-descriptor reactor data used for the pipe. reactor::per_descriptor_data reactor_data_; -#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) // A mapping from signal number to the registered signal sets. registration* registrations_[max_signal_number]; diff --git a/include/boost/asio/detail/socket_ops.hpp b/include/boost/asio/detail/socket_ops.hpp index da736fa1..d09e27ea 100644 --- a/include/boost/asio/detail/socket_ops.hpp +++ b/include/boost/asio/detail/socket_ops.hpp @@ -63,6 +63,8 @@ struct noop_deleter { void operator()(void*) {} }; typedef shared_ptr shared_cancel_token_type; typedef weak_ptr weak_cancel_token_type; +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + BOOST_ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr, std::size_t* addrlen, boost::system::error_code& ec); @@ -107,7 +109,6 @@ BOOST_ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr, std::size_t addrlen, boost::system::error_code& ec); BOOST_ASIO_DECL bool non_blocking_connect(socket_type s, - const socket_addr_type* addr, std::size_t addrlen, boost::system::error_code& ec); BOOST_ASIO_DECL int socketpair(int af, int type, int protocol, @@ -264,6 +265,8 @@ BOOST_ASIO_DECL int poll_write(socket_type s, BOOST_ASIO_DECL int poll_connect(socket_type s, boost::system::error_code& ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + BOOST_ASIO_DECL const char* inet_ntop(int af, const void* src, char* dest, size_t length, unsigned long scope_id, boost::system::error_code& ec); @@ -273,6 +276,8 @@ BOOST_ASIO_DECL int inet_pton(int af, const char* src, void* dest, BOOST_ASIO_DECL int gethostname(char* name, int namelen, boost::system::error_code& ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + BOOST_ASIO_DECL boost::system::error_code getaddrinfo(const char* host, const char* service, const addrinfo_type& hints, addrinfo_type** result, boost::system::error_code& ec); @@ -300,6 +305,8 @@ BOOST_ASIO_DECL boost::system::error_code background_getnameinfo( char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, boost::system::error_code& ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + BOOST_ASIO_DECL u_long_type network_to_host_long(u_long_type value); BOOST_ASIO_DECL u_long_type host_to_network_long(u_long_type value); diff --git a/include/boost/asio/detail/socket_option.hpp b/include/boost/asio/detail/socket_option.hpp index 6f28dc57..80cf3ea0 100644 --- a/include/boost/asio/detail/socket_option.hpp +++ b/include/boost/asio/detail/socket_option.hpp @@ -274,14 +274,14 @@ public: // Get the address of the linger data. template - ::linger* data(const Protocol&) + detail::linger_type* data(const Protocol&) { return &value_; } // Get the address of the linger data. template - const ::linger* data(const Protocol&) const + const detail::linger_type* data(const Protocol&) const { return &value_; } @@ -305,7 +305,7 @@ public: } private: - ::linger value_; + detail::linger_type value_; }; } // namespace socket_option diff --git a/include/boost/asio/detail/socket_select_interrupter.hpp b/include/boost/asio/detail/socket_select_interrupter.hpp index 94fc3d7e..c0c2a2b1 100644 --- a/include/boost/asio/detail/socket_select_interrupter.hpp +++ b/include/boost/asio/detail/socket_select_interrupter.hpp @@ -17,6 +17,8 @@ #include +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #if defined(BOOST_ASIO_WINDOWS) \ || defined(__CYGWIN__) \ || defined(__SYMBIAN32__) @@ -86,4 +88,6 @@ private: // || defined(__CYGWIN__) // || defined(__SYMBIAN32__) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + #endif // BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP diff --git a/include/boost/asio/detail/socket_types.hpp b/include/boost/asio/detail/socket_types.hpp index e17c77fd..3ab5c4d9 100644 --- a/include/boost/asio/detail/socket_types.hpp +++ b/include/boost/asio/detail/socket_types.hpp @@ -17,7 +17,9 @@ #include -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +// Empty. +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) # if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) # error WinSock.h has already been included # endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) @@ -28,6 +30,11 @@ # define BOOST_ASIO_WSPIAPI_H_DEFINED # endif // !defined(_WSPIAPI_H_) # endif // defined(__BORLANDC__) +# if defined(WINAPI_FAMILY) +# if ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0) +# include +# endif // ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0) +# endif // defined(WINAPI_FAMILY) # include # include # include @@ -81,7 +88,88 @@ namespace boost { namespace asio { namespace detail { -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +const int max_addr_v4_str_len = 256; +const int max_addr_v6_str_len = 256; +typedef unsigned __int32 u_long_type; +typedef unsigned __int16 u_short_type; +struct in4_addr_type { u_long_type s_addr; }; +struct in4_mreq_type { in4_addr_type imr_multiaddr, imr_interface; }; +struct in6_addr_type { unsigned char s6_addr[16]; }; +struct in6_mreq_type { in6_addr_type ipv6mr_multiaddr; + unsigned long ipv6mr_interface; }; +struct socket_addr_type { int sa_family; }; +struct sockaddr_in4_type { int sin_family; + in4_addr_type sin_addr; u_short_type sin_port; }; +struct sockaddr_in6_type { int sin6_family; + in6_addr_type sin6_addr; u_short_type sin6_port; + u_long_type sin6_flowinfo; u_long_type sin6_scope_id; }; +struct sockaddr_storage_type { int ss_family; + unsigned char ss_bytes[128 - sizeof(int)]; }; +struct addrinfo_type { int ai_flags; + int ai_family, ai_socktype, ai_protocol; + int ai_addrlen; const void* ai_addr; + const char* ai_canonname; addrinfo_type* ai_next; }; +struct linger_type { u_short_type l_onoff, l_linger; }; +typedef u_long_type ioctl_arg_type; +typedef int signed_size_type; +# define BOOST_ASIO_OS_DEF(c) BOOST_ASIO_OS_DEF_##c +# define BOOST_ASIO_OS_DEF_AF_UNSPEC 0 +# define BOOST_ASIO_OS_DEF_AF_INET 2 +# define BOOST_ASIO_OS_DEF_AF_INET6 23 +# define BOOST_ASIO_OS_DEF_SOCK_STREAM 1 +# define BOOST_ASIO_OS_DEF_SOCK_DGRAM 2 +# define BOOST_ASIO_OS_DEF_SOCK_RAW 3 +# define BOOST_ASIO_OS_DEF_SOCK_SEQPACKET 5 +# define BOOST_ASIO_OS_DEF_IPPROTO_IP 0 +# define BOOST_ASIO_OS_DEF_IPPROTO_IPV6 41 +# define BOOST_ASIO_OS_DEF_IPPROTO_TCP 6 +# define BOOST_ASIO_OS_DEF_IPPROTO_UDP 17 +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMP 1 +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMPV6 58 +# define BOOST_ASIO_OS_DEF_FIONBIO 1 +# define BOOST_ASIO_OS_DEF_FIONREAD 2 +# define BOOST_ASIO_OS_DEF_INADDR_ANY 0 +# define BOOST_ASIO_OS_DEF_MSG_OOB 0x1 +# define BOOST_ASIO_OS_DEF_MSG_PEEK 0x2 +# define BOOST_ASIO_OS_DEF_MSG_DONTROUTE 0x4 +# define BOOST_ASIO_OS_DEF_MSG_EOR 0 // Not supported. +# define BOOST_ASIO_OS_DEF_SHUT_RD 0x0 +# define BOOST_ASIO_OS_DEF_SHUT_WR 0x1 +# define BOOST_ASIO_OS_DEF_SHUT_RDWR 0x2 +# define BOOST_ASIO_OS_DEF_SOMAXCONN 0x7fffffff +# define BOOST_ASIO_OS_DEF_SOL_SOCKET 0xffff +# define BOOST_ASIO_OS_DEF_SO_BROADCAST 0x20 +# define BOOST_ASIO_OS_DEF_SO_DEBUG 0x1 +# define BOOST_ASIO_OS_DEF_SO_DONTROUTE 0x10 +# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE 0x8 +# define BOOST_ASIO_OS_DEF_SO_LINGER 0x80 +# define BOOST_ASIO_OS_DEF_SO_SNDBUF 0x1001 +# define BOOST_ASIO_OS_DEF_SO_RCVBUF 0x1002 +# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT 0x1003 +# define BOOST_ASIO_OS_DEF_SO_RCVLOWAT 0x1004 +# define BOOST_ASIO_OS_DEF_SO_REUSEADDR 0x4 +# define BOOST_ASIO_OS_DEF_TCP_NODELAY 0x1 +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_IF 2 +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_TTL 3 +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_LOOP 4 +# define BOOST_ASIO_OS_DEF_IP_ADD_MEMBERSHIP 5 +# define BOOST_ASIO_OS_DEF_IP_DROP_MEMBERSHIP 6 +# define BOOST_ASIO_OS_DEF_IP_TTL 7 +# define BOOST_ASIO_OS_DEF_IPV6_UNICAST_HOPS 4 +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_IF 9 +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_HOPS 10 +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_LOOP 11 +# define BOOST_ASIO_OS_DEF_IPV6_JOIN_GROUP 12 +# define BOOST_ASIO_OS_DEF_IPV6_LEAVE_GROUP 13 +# define BOOST_ASIO_OS_DEF_AI_CANONNAME 0x2 +# define BOOST_ASIO_OS_DEF_AI_PASSIVE 0x1 +# define BOOST_ASIO_OS_DEF_AI_NUMERICHOST 0x4 +# define BOOST_ASIO_OS_DEF_AI_NUMERICSERV 0x8 +# define BOOST_ASIO_OS_DEF_AI_V4MAPPED 0x800 +# define BOOST_ASIO_OS_DEF_AI_ALL 0x100 +# define BOOST_ASIO_OS_DEF_AI_ADDRCONFIG 0x400 +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) typedef SOCKET socket_type; const SOCKET invalid_socket = INVALID_SOCKET; const int socket_error_retval = SOCKET_ERROR; @@ -104,17 +192,83 @@ typedef sockaddr_in6 sockaddr_in6_type; typedef sockaddr_storage sockaddr_storage_type; typedef addrinfo addrinfo_type; # endif +typedef ::linger linger_type; typedef unsigned long ioctl_arg_type; typedef u_long u_long_type; typedef u_short u_short_type; typedef int signed_size_type; -const int shutdown_receive = SD_RECEIVE; -const int shutdown_send = SD_SEND; -const int shutdown_both = SD_BOTH; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -const int message_end_of_record = 0; // Not supported on Windows. +# define BOOST_ASIO_OS_DEF(c) BOOST_ASIO_OS_DEF_##c +# define BOOST_ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC +# define BOOST_ASIO_OS_DEF_AF_INET AF_INET +# define BOOST_ASIO_OS_DEF_AF_INET6 AF_INET6 +# define BOOST_ASIO_OS_DEF_SOCK_STREAM SOCK_STREAM +# define BOOST_ASIO_OS_DEF_SOCK_DGRAM SOCK_DGRAM +# define BOOST_ASIO_OS_DEF_SOCK_RAW SOCK_RAW +# define BOOST_ASIO_OS_DEF_SOCK_SEQPACKET SOCK_SEQPACKET +# define BOOST_ASIO_OS_DEF_IPPROTO_IP IPPROTO_IP +# define BOOST_ASIO_OS_DEF_IPPROTO_IPV6 IPPROTO_IPV6 +# define BOOST_ASIO_OS_DEF_IPPROTO_TCP IPPROTO_TCP +# define BOOST_ASIO_OS_DEF_IPPROTO_UDP IPPROTO_UDP +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMP IPPROTO_ICMP +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMPV6 IPPROTO_ICMPV6 +# define BOOST_ASIO_OS_DEF_FIONBIO FIONBIO +# define BOOST_ASIO_OS_DEF_FIONREAD FIONREAD +# define BOOST_ASIO_OS_DEF_INADDR_ANY INADDR_ANY +# define BOOST_ASIO_OS_DEF_MSG_OOB MSG_OOB +# define BOOST_ASIO_OS_DEF_MSG_PEEK MSG_PEEK +# define BOOST_ASIO_OS_DEF_MSG_DONTROUTE MSG_DONTROUTE +# define BOOST_ASIO_OS_DEF_MSG_EOR 0 // Not supported on Windows. +# define BOOST_ASIO_OS_DEF_SHUT_RD SD_RECEIVE +# define BOOST_ASIO_OS_DEF_SHUT_WR SD_SEND +# define BOOST_ASIO_OS_DEF_SHUT_RDWR SD_BOTH +# define BOOST_ASIO_OS_DEF_SOMAXCONN SOMAXCONN +# define BOOST_ASIO_OS_DEF_SOL_SOCKET SOL_SOCKET +# define BOOST_ASIO_OS_DEF_SO_BROADCAST SO_BROADCAST +# define BOOST_ASIO_OS_DEF_SO_DEBUG SO_DEBUG +# define BOOST_ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE +# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE +# define BOOST_ASIO_OS_DEF_SO_LINGER SO_LINGER +# define BOOST_ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF +# define BOOST_ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF +# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT +# define BOOST_ASIO_OS_DEF_SO_RCVLOWAT SO_RCVLOWAT +# define BOOST_ASIO_OS_DEF_SO_REUSEADDR SO_REUSEADDR +# define BOOST_ASIO_OS_DEF_TCP_NODELAY TCP_NODELAY +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_IF IP_MULTICAST_IF +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_TTL IP_MULTICAST_TTL +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_LOOP IP_MULTICAST_LOOP +# define BOOST_ASIO_OS_DEF_IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP +# define BOOST_ASIO_OS_DEF_IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP +# define BOOST_ASIO_OS_DEF_IP_TTL IP_TTL +# define BOOST_ASIO_OS_DEF_IPV6_UNICAST_HOPS IPV6_UNICAST_HOPS +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_IF IPV6_MULTICAST_IF +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_HOPS IPV6_MULTICAST_HOPS +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_LOOP IPV6_MULTICAST_LOOP +# define BOOST_ASIO_OS_DEF_IPV6_JOIN_GROUP IPV6_JOIN_GROUP +# define BOOST_ASIO_OS_DEF_IPV6_LEAVE_GROUP IPV6_LEAVE_GROUP +# define BOOST_ASIO_OS_DEF_AI_CANONNAME AI_CANONNAME +# define BOOST_ASIO_OS_DEF_AI_PASSIVE AI_PASSIVE +# define BOOST_ASIO_OS_DEF_AI_NUMERICHOST AI_NUMERICHOST +# if defined(AI_NUMERICSERV) +# define BOOST_ASIO_OS_DEF_AI_NUMERICSERV AI_NUMERICSERV +# else +# define BOOST_ASIO_OS_DEF_AI_NUMERICSERV 0 +# endif +# if defined(AI_V4MAPPED) +# define BOOST_ASIO_OS_DEF_AI_V4MAPPED AI_V4MAPPED +# else +# define BOOST_ASIO_OS_DEF_AI_V4MAPPED 0 +# endif +# if defined(AI_ALL) +# define BOOST_ASIO_OS_DEF_AI_ALL AI_ALL +# else +# define BOOST_ASIO_OS_DEF_AI_ALL 0 +# endif +# if defined(AI_ADDRCONFIG) +# define BOOST_ASIO_OS_DEF_AI_ADDRCONFIG AI_ADDRCONFIG +# else +# define BOOST_ASIO_OS_DEF_AI_ADDRCONFIG 0 +# endif # if defined (_WIN32_WINNT) const int max_iov_len = 64; # else @@ -149,6 +303,7 @@ typedef sockaddr_in6 sockaddr_in6_type; typedef sockaddr_storage sockaddr_storage_type; typedef sockaddr_un sockaddr_un_type; typedef addrinfo addrinfo_type; +typedef ::linger linger_type; typedef int ioctl_arg_type; typedef uint32_t u_long_type; typedef uint16_t u_short_type; @@ -157,13 +312,80 @@ typedef ssize_t signed_size_type; #else // defined(BOOST_ASIO_HAS_SSIZE_T) typedef int signed_size_type; #endif // defined(BOOST_ASIO_HAS_SSIZE_T) -const int shutdown_receive = SHUT_RD; -const int shutdown_send = SHUT_WR; -const int shutdown_both = SHUT_RDWR; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -const int message_end_of_record = MSG_EOR; +# define BOOST_ASIO_OS_DEF(c) BOOST_ASIO_OS_DEF_##c +# define BOOST_ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC +# define BOOST_ASIO_OS_DEF_AF_INET AF_INET +# define BOOST_ASIO_OS_DEF_AF_INET6 AF_INET6 +# define BOOST_ASIO_OS_DEF_SOCK_STREAM SOCK_STREAM +# define BOOST_ASIO_OS_DEF_SOCK_DGRAM SOCK_DGRAM +# define BOOST_ASIO_OS_DEF_SOCK_RAW SOCK_RAW +# define BOOST_ASIO_OS_DEF_SOCK_SEQPACKET SOCK_SEQPACKET +# define BOOST_ASIO_OS_DEF_IPPROTO_IP IPPROTO_IP +# define BOOST_ASIO_OS_DEF_IPPROTO_IPV6 IPPROTO_IPV6 +# define BOOST_ASIO_OS_DEF_IPPROTO_TCP IPPROTO_TCP +# define BOOST_ASIO_OS_DEF_IPPROTO_UDP IPPROTO_UDP +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMP IPPROTO_ICMP +# define BOOST_ASIO_OS_DEF_IPPROTO_ICMPV6 IPPROTO_ICMPV6 +# define BOOST_ASIO_OS_DEF_FIONBIO FIONBIO +# define BOOST_ASIO_OS_DEF_FIONREAD FIONREAD +# define BOOST_ASIO_OS_DEF_INADDR_ANY INADDR_ANY +# define BOOST_ASIO_OS_DEF_MSG_OOB MSG_OOB +# define BOOST_ASIO_OS_DEF_MSG_PEEK MSG_PEEK +# define BOOST_ASIO_OS_DEF_MSG_DONTROUTE MSG_DONTROUTE +# define BOOST_ASIO_OS_DEF_MSG_EOR MSG_EOR +# define BOOST_ASIO_OS_DEF_SHUT_RD SHUT_RD +# define BOOST_ASIO_OS_DEF_SHUT_WR SHUT_WR +# define BOOST_ASIO_OS_DEF_SHUT_RDWR SHUT_RDWR +# define BOOST_ASIO_OS_DEF_SOMAXCONN SOMAXCONN +# define BOOST_ASIO_OS_DEF_SOL_SOCKET SOL_SOCKET +# define BOOST_ASIO_OS_DEF_SO_BROADCAST SO_BROADCAST +# define BOOST_ASIO_OS_DEF_SO_DEBUG SO_DEBUG +# define BOOST_ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE +# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE +# define BOOST_ASIO_OS_DEF_SO_LINGER SO_LINGER +# define BOOST_ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF +# define BOOST_ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF +# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT +# define BOOST_ASIO_OS_DEF_SO_RCVLOWAT SO_RCVLOWAT +# define BOOST_ASIO_OS_DEF_SO_REUSEADDR SO_REUSEADDR +# define BOOST_ASIO_OS_DEF_TCP_NODELAY TCP_NODELAY +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_IF IP_MULTICAST_IF +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_TTL IP_MULTICAST_TTL +# define BOOST_ASIO_OS_DEF_IP_MULTICAST_LOOP IP_MULTICAST_LOOP +# define BOOST_ASIO_OS_DEF_IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP +# define BOOST_ASIO_OS_DEF_IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP +# define BOOST_ASIO_OS_DEF_IP_TTL IP_TTL +# define BOOST_ASIO_OS_DEF_IPV6_UNICAST_HOPS IPV6_UNICAST_HOPS +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_IF IPV6_MULTICAST_IF +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_HOPS IPV6_MULTICAST_HOPS +# define BOOST_ASIO_OS_DEF_IPV6_MULTICAST_LOOP IPV6_MULTICAST_LOOP +# define BOOST_ASIO_OS_DEF_IPV6_JOIN_GROUP IPV6_JOIN_GROUP +# define BOOST_ASIO_OS_DEF_IPV6_LEAVE_GROUP IPV6_LEAVE_GROUP +# define BOOST_ASIO_OS_DEF_AI_CANONNAME AI_CANONNAME +# define BOOST_ASIO_OS_DEF_AI_PASSIVE AI_PASSIVE +# define BOOST_ASIO_OS_DEF_AI_NUMERICHOST AI_NUMERICHOST +# if defined(AI_NUMERICSERV) +# define BOOST_ASIO_OS_DEF_AI_NUMERICSERV AI_NUMERICSERV +# else +# define BOOST_ASIO_OS_DEF_AI_NUMERICSERV 0 +# endif +// Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but +// does not implement them. Therefore they are specifically excluded here. +# if defined(AI_V4MAPPED) && !defined(__QNXNTO__) +# define BOOST_ASIO_OS_DEF_AI_V4MAPPED AI_V4MAPPED +# else +# define BOOST_ASIO_OS_DEF_AI_V4MAPPED 0 +# endif +# if defined(AI_ALL) && !defined(__QNXNTO__) +# define BOOST_ASIO_OS_DEF_AI_ALL AI_ALL +# else +# define BOOST_ASIO_OS_DEF_AI_ALL 0 +# endif +# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__) +# define BOOST_ASIO_OS_DEF_AI_ADDRCONFIG AI_ADDRCONFIG +# else +# define BOOST_ASIO_OS_DEF_AI_ADDRCONFIG 0 +# endif # if defined(IOV_MAX) const int max_iov_len = IOV_MAX; # else diff --git a/include/boost/asio/detail/static_mutex.hpp b/include/boost/asio/detail/static_mutex.hpp index ef39406b..10488b18 100644 --- a/include/boost/asio/detail/static_mutex.hpp +++ b/include/boost/asio/detail/static_mutex.hpp @@ -23,6 +23,8 @@ # include #elif defined(BOOST_ASIO_HAS_PTHREADS) # include +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# include #else # error Only Windows and POSIX are supported! #endif @@ -40,6 +42,9 @@ typedef win_static_mutex static_mutex; #elif defined(BOOST_ASIO_HAS_PTHREADS) typedef posix_static_mutex static_mutex; # define BOOST_ASIO_STATIC_MUTEX_INIT BOOST_ASIO_POSIX_STATIC_MUTEX_INIT +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +typedef std_static_mutex static_mutex; +# define BOOST_ASIO_STATIC_MUTEX_INIT BOOST_ASIO_STD_STATIC_MUTEX_INIT #endif } // namespace detail diff --git a/include/boost/asio/detail/std_event.hpp b/include/boost/asio/detail/std_event.hpp new file mode 100644 index 00000000..816ef491 --- /dev/null +++ b/include/boost/asio/detail/std_event.hpp @@ -0,0 +1,129 @@ +// +// detail/std_event.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_STD_EVENT_HPP +#define BOOST_ASIO_DETAIL_STD_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class std_event + : private noncopyable +{ +public: + // Constructor. + std_event() + : signalled_(false) + { + } + + // Destructor. + ~std_event() + { + } + + // Signal the event. + template + void signal(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + (void)lock; + signalled_ = true; + cond_.notify_one(); + } + + // Signal the event and unlock the mutex. + template + void signal_and_unlock(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + signalled_ = true; + lock.unlock(); + cond_.notify_one(); + } + + // Reset the event. + template + void clear(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + (void)lock; + signalled_ = false; + } + + // Wait for the event to become signalled. + template + void wait(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + unique_lock_adapter u_lock(lock); + while (!signalled_) + cond_.wait(u_lock.unique_lock_); + } + + // Timed wait for the event to become signalled. + template + bool wait_for_usec(Lock& lock, long usec) + { + BOOST_ASIO_ASSERT(lock.locked()); + unique_lock_adapter u_lock(lock); + if (!signalled_) + cond_.wait_for(u_lock.unique_lock_, std::chrono::microseconds(usec)); + return signalled_; + } + +private: + // Helper class to temporarily adapt a scoped_lock into a unique_lock so that + // it can be passed to std::condition_variable::wait(). + struct unique_lock_adapter + { + template + explicit unique_lock_adapter(Lock& lock) + : unique_lock_(lock.mutex().mutex_, std::adopt_lock) + { + } + + ~unique_lock_adapter() + { + unique_lock_.release(); + } + + std::unique_lock unique_lock_; + }; + + std::condition_variable cond_; + bool signalled_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#endif // BOOST_ASIO_DETAIL_STD_EVENT_HPP diff --git a/include/boost/asio/detail/std_mutex.hpp b/include/boost/asio/detail/std_mutex.hpp new file mode 100644 index 00000000..19fdd187 --- /dev/null +++ b/include/boost/asio/detail/std_mutex.hpp @@ -0,0 +1,75 @@ +// +// detail/std_mutex.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_STD_MUTEX_HPP +#define BOOST_ASIO_DETAIL_STD_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class std_event; + +class std_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + std_mutex() + { + } + + // Destructor. + ~std_mutex() + { + } + + // Lock the mutex. + void lock() + { + mutex_.lock(); + } + + // Unlock the mutex. + void unlock() + { + mutex_.unlock(); + } + +private: + friend class std_event; + std::mutex mutex_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#endif // BOOST_ASIO_DETAIL_STD_MUTEX_HPP diff --git a/include/boost/asio/detail/std_static_mutex.hpp b/include/boost/asio/detail/std_static_mutex.hpp new file mode 100644 index 00000000..b083a4e3 --- /dev/null +++ b/include/boost/asio/detail/std_static_mutex.hpp @@ -0,0 +1,83 @@ +// +// detail/std_static_mutex.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_STD_STATIC_MUTEX_HPP +#define BOOST_ASIO_DETAIL_STD_STATIC_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class std_event; + +class std_static_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + std_static_mutex(int) + { + } + + // Destructor. + ~std_static_mutex() + { + } + + // Initialise the mutex. + void init() + { + // Nothing to do. + } + + // Lock the mutex. + void lock() + { + mutex_.lock(); + } + + // Unlock the mutex. + void unlock() + { + mutex_.unlock(); + } + +private: + friend class std_event; + std::mutex mutex_; +}; + +#define BOOST_ASIO_STD_STATIC_MUTEX_INIT 0 + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +#endif // BOOST_ASIO_DETAIL_STD_STATIC_MUTEX_HPP diff --git a/include/boost/asio/detail/std_thread.hpp b/include/boost/asio/detail/std_thread.hpp new file mode 100644 index 00000000..a2fabaff --- /dev/null +++ b/include/boost/asio/detail/std_thread.hpp @@ -0,0 +1,67 @@ +// +// detail/std_thread.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_STD_THREAD_HPP +#define BOOST_ASIO_DETAIL_STD_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_STD_THREAD) + +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class std_thread + : private noncopyable +{ +public: + // Constructor. + template + std_thread(Function f, unsigned int = 0) + : thread_(f) + { + } + + // Destructor. + ~std_thread() + { + join(); + } + + // Wait for the thread to exit. + void join() + { + if (thread_.joinable()) + thread_.join(); + } + +private: + std::thread thread_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_STD_THREAD) + +#endif // BOOST_ASIO_DETAIL_STD_THREAD_HPP diff --git a/include/boost/asio/detail/task_io_service.hpp b/include/boost/asio/detail/task_io_service.hpp index 8b9783dd..8f3e2601 100644 --- a/include/boost/asio/detail/task_io_service.hpp +++ b/include/boost/asio/detail/task_io_service.hpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -35,6 +34,8 @@ namespace boost { namespace asio { namespace detail { +struct task_io_service_thread_info; + class task_io_service : public boost::asio::detail::service_base { diff --git a/include/boost/asio/detail/task_io_service_fwd.hpp b/include/boost/asio/detail/task_io_service_fwd.hpp deleted file mode 100644 index fa5a286a..00000000 --- a/include/boost/asio/detail/task_io_service_fwd.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// detail/task_io_service_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP -#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -namespace boost { -namespace asio { -namespace detail { - -class task_io_service; -class task_io_service_operation; -struct task_io_service_thread_info; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP diff --git a/include/boost/asio/detail/task_io_service_operation.hpp b/include/boost/asio/detail/task_io_service_operation.hpp index ceb3d443..95811959 100644 --- a/include/boost/asio/detail/task_io_service_operation.hpp +++ b/include/boost/asio/detail/task_io_service_operation.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #include @@ -26,6 +25,8 @@ namespace boost { namespace asio { namespace detail { +class task_io_service; + // Base class for all operations. A function pointer is used instead of virtual // functions to avoid the associated overhead. class task_io_service_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER diff --git a/include/boost/asio/detail/task_io_service_thread_info.hpp b/include/boost/asio/detail/task_io_service_thread_info.hpp index 4fcfac9c..5a5a8b0a 100644 --- a/include/boost/asio/detail/task_io_service_thread_info.hpp +++ b/include/boost/asio/detail/task_io_service_thread_info.hpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -26,6 +25,9 @@ namespace boost { namespace asio { namespace detail { +class task_io_service; +class task_io_service_operation; + struct task_io_service_thread_info : public thread_info_base { event* wakeup_event; diff --git a/include/boost/asio/detail/thread.hpp b/include/boost/asio/detail/thread.hpp index 11bcd16a..dde5d812 100644 --- a/include/boost/asio/detail/thread.hpp +++ b/include/boost/asio/detail/thread.hpp @@ -27,8 +27,10 @@ # endif #elif defined(BOOST_ASIO_HAS_PTHREADS) # include +#elif defined(BOOST_ASIO_HAS_STD_THREAD) +# include #else -# error Only Windows and POSIX are supported! +# error Only Windows, POSIX and std::thread are supported! #endif namespace boost { @@ -45,6 +47,8 @@ typedef win_thread thread; # endif #elif defined(BOOST_ASIO_HAS_PTHREADS) typedef posix_thread thread; +#elif defined(BOOST_ASIO_HAS_STD_THREAD) +typedef std_thread thread; #endif } // namespace detail diff --git a/include/boost/asio/detail/timer_queue_base.hpp b/include/boost/asio/detail/timer_queue_base.hpp index 2a1e8445..1b69fec3 100644 --- a/include/boost/asio/detail/timer_queue_base.hpp +++ b/include/boost/asio/detail/timer_queue_base.hpp @@ -58,6 +58,9 @@ private: timer_queue_base* next_; }; +template +class timer_queue; + } // namespace detail } // namespace asio } // namespace boost diff --git a/include/boost/asio/detail/timer_queue_fwd.hpp b/include/boost/asio/detail/timer_queue_fwd.hpp deleted file mode 100644 index 846d512b..00000000 --- a/include/boost/asio/detail/timer_queue_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// detail/timer_queue_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP -#define BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -namespace boost { -namespace asio { -namespace detail { - -template -class timer_queue; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP diff --git a/include/boost/asio/detail/timer_scheduler.hpp b/include/boost/asio/detail/timer_scheduler.hpp index e0bd35a1..84f5ba91 100644 --- a/include/boost/asio/detail/timer_scheduler.hpp +++ b/include/boost/asio/detail/timer_scheduler.hpp @@ -18,7 +18,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #elif defined(BOOST_ASIO_HAS_EPOLL) # include diff --git a/include/boost/asio/detail/timer_scheduler_fwd.hpp b/include/boost/asio/detail/timer_scheduler_fwd.hpp index 90545f3b..af86ee58 100644 --- a/include/boost/asio/detail/timer_scheduler_fwd.hpp +++ b/include/boost/asio/detail/timer_scheduler_fwd.hpp @@ -17,32 +17,22 @@ #include -#if defined(BOOST_ASIO_HAS_IOCP) -# include -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include -#else -# include -#endif - namespace boost { namespace asio { namespace detail { -#if defined(BOOST_ASIO_HAS_IOCP) -typedef win_iocp_io_service timer_scheduler; +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +typedef class winrt_timer_scheduler timer_scheduler; +#elif defined(BOOST_ASIO_HAS_IOCP) +typedef class win_iocp_io_service timer_scheduler; #elif defined(BOOST_ASIO_HAS_EPOLL) -typedef epoll_reactor timer_scheduler; +typedef class epoll_reactor timer_scheduler; #elif defined(BOOST_ASIO_HAS_KQUEUE) -typedef kqueue_reactor timer_scheduler; +typedef class kqueue_reactor timer_scheduler; #elif defined(BOOST_ASIO_HAS_DEV_POLL) -typedef dev_poll_reactor timer_scheduler; +typedef class dev_poll_reactor timer_scheduler; #else -typedef select_reactor timer_scheduler; +typedef class select_reactor timer_scheduler; #endif } // namespace detail diff --git a/include/boost/asio/detail/variadic_templates.hpp b/include/boost/asio/detail/variadic_templates.hpp new file mode 100644 index 00000000..45996cc9 --- /dev/null +++ b/include/boost/asio/detail/variadic_templates.hpp @@ -0,0 +1,63 @@ +// +// detail/variadic_templates.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_VARIADIC_TEMPLATES_HPP +#define BOOST_ASIO_DETAIL_VARIADIC_TEMPLATES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +# define BOOST_ASIO_VARIADIC_TPARAMS(n) BOOST_ASIO_VARIADIC_TPARAMS_##n + +# define BOOST_ASIO_VARIADIC_TPARAMS_1 \ + typename T1 +# define BOOST_ASIO_VARIADIC_TPARAMS_2 \ + typename T1, typename T2 +# define BOOST_ASIO_VARIADIC_TPARAMS_3 \ + typename T1, typename T2, typename T3 +# define BOOST_ASIO_VARIADIC_TPARAMS_4 \ + typename T1, typename T2, typename T3, typename T4 +# define BOOST_ASIO_VARIADIC_TPARAMS_5 \ + typename T1, typename T2, typename T3, typename T4, typename T5 + +# define BOOST_ASIO_VARIADIC_TARGS(n) BOOST_ASIO_VARIADIC_TARGS_##n + +# define BOOST_ASIO_VARIADIC_TARGS_1 x1 +# define BOOST_ASIO_VARIADIC_TARGS_2 x1, x2 +# define BOOST_ASIO_VARIADIC_TARGS_3 x1, x2, x3 +# define BOOST_ASIO_VARIADIC_TARGS_4 x1, x2, x3, x4 +# define BOOST_ASIO_VARIADIC_TARGS_5 x1, x2, x3, x4, x5 + +# define BOOST_ASIO_VARIADIC_PARAMS(n) BOOST_ASIO_VARIADIC_PARAMS_##n + +# define BOOST_ASIO_VARIADIC_PARAMS_1 T1 x1 +# define BOOST_ASIO_VARIADIC_PARAMS_2 T1 x1, T2 x2 +# define BOOST_ASIO_VARIADIC_PARAMS_3 T1 x1, T2 x2, T3 x3 +# define BOOST_ASIO_VARIADIC_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4 +# define BOOST_ASIO_VARIADIC_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5 + +# define BOOST_ASIO_VARIADIC_ARGS(n) BOOST_ASIO_VARIADIC_ARGS_##n + +# define BOOST_ASIO_VARIADIC_ARGS_1 x1 +# define BOOST_ASIO_VARIADIC_ARGS_2 x1, x2 +# define BOOST_ASIO_VARIADIC_ARGS_3 x1, x2, x3 +# define BOOST_ASIO_VARIADIC_ARGS_4 x1, x2, x3, x4 +# define BOOST_ASIO_VARIADIC_ARGS_5 x1, x2, x3, x4, x5 + +# define BOOST_ASIO_VARIADIC_GENERATE(m) m(1) m(2) m(3) m(4) m(5) + +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#endif // BOOST_ASIO_DETAIL_VARIADIC_TEMPLATES_HPP diff --git a/include/boost/asio/detail/win_iocp_io_service.hpp b/include/boost/asio/detail/win_iocp_io_service.hpp index 60222d5c..de7d0279 100644 --- a/include/boost/asio/detail/win_iocp_io_service.hpp +++ b/include/boost/asio/detail/win_iocp_io_service.hpp @@ -28,10 +28,8 @@ #include #include #include -#include #include #include -#include #include #include diff --git a/include/boost/asio/detail/win_iocp_io_service_fwd.hpp b/include/boost/asio/detail/win_iocp_io_service_fwd.hpp deleted file mode 100644 index b833f583..00000000 --- a/include/boost/asio/detail/win_iocp_io_service_fwd.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// detail/win_iocp_io_service_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP -#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include - -#if defined(BOOST_ASIO_HAS_IOCP) - -namespace boost { -namespace asio { -namespace detail { - -class win_iocp_io_service; -class win_iocp_overlapped_ptr; - -} // namespace detail -} // namespace asio -} // namespace boost - -#endif // defined(BOOST_ASIO_HAS_IOCP) - -#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP diff --git a/include/boost/asio/detail/win_iocp_operation.hpp b/include/boost/asio/detail/win_iocp_operation.hpp index 549da82f..87ca1303 100644 --- a/include/boost/asio/detail/win_iocp_operation.hpp +++ b/include/boost/asio/detail/win_iocp_operation.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,8 @@ namespace boost { namespace asio { namespace detail { +class win_iocp_io_service; + // Base class for all operations. A function pointer is used instead of virtual // functions to avoid the associated overhead. class win_iocp_operation diff --git a/include/boost/asio/detail/win_iocp_socket_service.hpp b/include/boost/asio/detail/win_iocp_socket_service.hpp index 24690d58..80b6361e 100644 --- a/include/boost/asio/detail/win_iocp_socket_service.hpp +++ b/include/boost/asio/detail/win_iocp_socket_service.hpp @@ -166,6 +166,24 @@ public: other_impl.remote_endpoint_ = endpoint_type(); } + // Move-construct a new socket implementation from another protocol type. + template + void converting_move_construct(implementation_type& impl, + typename win_iocp_socket_service< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + + impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_; + other_impl.have_remote_endpoint_ = false; + + impl.remote_endpoint_ = other_impl.remote_endpoint_; + other_impl.remote_endpoint_ = typename Protocol1::endpoint(); + } + // Open a new socket implementation. boost::system::error_code open(implementation_type& impl, const protocol_type& protocol, boost::system::error_code& ec) @@ -433,7 +451,7 @@ public: peer_endpoint ? &addr_len : 0, ec)); // On success, assign new connection to peer socket object. - if (new_socket.get() >= 0) + if (new_socket.get() != invalid_socket) { if (peer_endpoint) peer_endpoint->resize(addr_len); @@ -484,11 +502,11 @@ public: const endpoint_type& peer_endpoint, Handler& handler) { // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_connect_op op; + typedef reactive_socket_connect_op op; typename op::ptr p = { boost::asio::detail::addressof(handler), boost_asio_handler_alloc_helpers::allocate( sizeof(op), handler), 0 }; - p.p = new (p.v) op(impl.socket_, peer_endpoint, handler); + p.p = new (p.v) op(impl.socket_, handler); BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect")); diff --git a/include/boost/asio/detail/win_iocp_socket_service_base.hpp b/include/boost/asio/detail/win_iocp_socket_service_base.hpp index 8b6a72f0..31cfa16c 100644 --- a/include/boost/asio/detail/win_iocp_socket_service_base.hpp +++ b/include/boost/asio/detail/win_iocp_socket_service_base.hpp @@ -215,7 +215,7 @@ public: template void async_send(base_implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_send_op op; @@ -238,7 +238,7 @@ public: // Start an asynchronous wait until data can be sent without blocking. template void async_send(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler handler) + socket_base::message_flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op op; @@ -282,7 +282,7 @@ public: template void async_receive(base_implementation_type& impl, const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_recv_op op; @@ -305,7 +305,7 @@ public: // Wait until data can be received without blocking. template void async_receive(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags flags, Handler handler) + socket_base::message_flags flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op op; @@ -356,7 +356,7 @@ public: template void async_receive_with_flags(base_implementation_type& impl, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler handler) + socket_base::message_flags& out_flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_recvmsg_op op; @@ -379,7 +379,7 @@ public: template void async_receive_with_flags(base_implementation_type& impl, const null_buffers&, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler handler) + socket_base::message_flags& out_flags, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op op; diff --git a/include/boost/asio/detail/win_object_handle_service.hpp b/include/boost/asio/detail/win_object_handle_service.hpp index edebf749..17889e19 100644 --- a/include/boost/asio/detail/win_object_handle_service.hpp +++ b/include/boost/asio/detail/win_object_handle_service.hpp @@ -130,7 +130,7 @@ public: /// Start an asynchronous wait. template - void async_wait(implementation_type& impl, Handler handler) + void async_wait(implementation_type& impl, Handler& handler) { // Allocate and construct an operation to wrap the handler. typedef wait_handler op; diff --git a/include/boost/asio/detail/winrt_async_manager.hpp b/include/boost/asio/detail/winrt_async_manager.hpp new file mode 100644 index 00000000..935903d7 --- /dev/null +++ b/include/boost/asio/detail/winrt_async_manager.hpp @@ -0,0 +1,296 @@ +// +// detail/winrt_async_manager.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP +#define BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class winrt_async_manager + : public boost::asio::detail::service_base +{ +public: + // Constructor. + winrt_async_manager(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + io_service_(use_service(io_service)), + outstanding_ops_(1) + { + } + + // Destructor. + ~winrt_async_manager() + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + if (--outstanding_ops_ > 0) + { + // Block until last operation is complete. + std::future f = promise_.get_future(); + f.wait(); + } + } + + void sync(Windows::Foundation::IAsyncAction^ action, + boost::system::error_code& ec) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto promise = std::make_shared>(); + auto future = promise->get_future(); + + action->Completed = ref new AsyncActionCompletedHandler( + [promise](IAsyncAction^ action, AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + promise->set_value(boost::asio::error::operation_aborted); + break; + case AsyncStatus::Error: + case AsyncStatus::Completed: + default: + boost::system::error_code ec( + action->ErrorCode.Value, + boost::system::system_category()); + promise->set_value(ec); + break; + } + }); + + ec = future.get(); + } + + template + TResult sync(Windows::Foundation::IAsyncOperation^ operation, + boost::system::error_code& ec) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto promise = std::make_shared>(); + auto future = promise->get_future(); + + operation->Completed = ref new AsyncOperationCompletedHandler( + [promise](IAsyncOperation^ operation, AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + promise->set_value(boost::asio::error::operation_aborted); + break; + case AsyncStatus::Error: + case AsyncStatus::Completed: + default: + boost::system::error_code ec( + operation->ErrorCode.Value, + boost::system::system_category()); + promise->set_value(ec); + break; + } + }); + + ec = future.get(); + return operation->GetResults(); + } + + template + TResult sync( + Windows::Foundation::IAsyncOperationWithProgress< + TResult, TProgress>^ operation, + boost::system::error_code& ec) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto promise = std::make_shared>(); + auto future = promise->get_future(); + + operation->Completed + = ref new AsyncOperationWithProgressCompletedHandler( + [promise](IAsyncOperationWithProgress^ operation, + AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + promise->set_value(boost::asio::error::operation_aborted); + break; + case AsyncStatus::Started: + break; + case AsyncStatus::Error: + case AsyncStatus::Completed: + default: + boost::system::error_code ec( + operation->ErrorCode.Value, + boost::system::system_category()); + promise->set_value(ec); + break; + } + }); + + ec = future.get(); + return operation->GetResults(); + } + + void async(Windows::Foundation::IAsyncAction^ action, + winrt_async_op* handler) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto on_completed = ref new AsyncActionCompletedHandler( + [this, handler](IAsyncAction^ action, AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + handler->ec_ = boost::asio::error::operation_aborted; + break; + case AsyncStatus::Started: + return; + case AsyncStatus::Completed: + case AsyncStatus::Error: + default: + handler->ec_ = boost::system::error_code( + action->ErrorCode.Value, + boost::system::system_category()); + break; + } + io_service_.post_deferred_completion(handler); + if (--outstanding_ops_ == 0) + promise_.set_value(); + }); + + io_service_.work_started(); + ++outstanding_ops_; + action->Completed = on_completed; + } + + template + void async(Windows::Foundation::IAsyncOperation^ operation, + winrt_async_op* handler) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto on_completed = ref new AsyncOperationCompletedHandler( + [this, handler](IAsyncOperation^ operation, AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + handler->ec_ = boost::asio::error::operation_aborted; + break; + case AsyncStatus::Started: + return; + case AsyncStatus::Completed: + handler->result_ = operation->GetResults(); + // Fall through. + case AsyncStatus::Error: + default: + handler->ec_ = boost::system::error_code( + operation->ErrorCode.Value, + boost::system::system_category()); + break; + } + io_service_.post_deferred_completion(handler); + if (--outstanding_ops_ == 0) + promise_.set_value(); + }); + + io_service_.work_started(); + ++outstanding_ops_; + operation->Completed = on_completed; + } + + template + void async( + Windows::Foundation::IAsyncOperationWithProgress< + TResult, TProgress>^ operation, + winrt_async_op* handler) + { + using namespace Windows::Foundation; + using Windows::Foundation::AsyncStatus; + + auto on_completed + = ref new AsyncOperationWithProgressCompletedHandler( + [this, handler](IAsyncOperationWithProgress< + TResult, TProgress>^ operation, AsyncStatus status) + { + switch (status) + { + case AsyncStatus::Canceled: + handler->ec_ = boost::asio::error::operation_aborted; + break; + case AsyncStatus::Started: + return; + case AsyncStatus::Completed: + handler->result_ = operation->GetResults(); + // Fall through. + case AsyncStatus::Error: + default: + handler->ec_ = boost::system::error_code( + operation->ErrorCode.Value, + boost::system::system_category()); + break; + } + io_service_.post_deferred_completion(handler); + if (--outstanding_ops_ == 0) + promise_.set_value(); + }); + + io_service_.work_started(); + ++outstanding_ops_; + operation->Completed = on_completed; + } + +private: + // The io_service implementation used to post completed handlers. + io_service_impl& io_service_; + + // Count of outstanding operations. + atomic_count outstanding_ops_; + + // Used to keep wait for outstanding operations to complete. + std::promise promise_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP diff --git a/include/boost/asio/detail/winrt_async_op.hpp b/include/boost/asio/detail/winrt_async_op.hpp new file mode 100644 index 00000000..376400e5 --- /dev/null +++ b/include/boost/asio/detail/winrt_async_op.hpp @@ -0,0 +1,67 @@ +// +// detail/winrt_async_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_ASYNC_OP_HPP +#define BOOST_ASIO_DETAIL_WINRT_ASYNC_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_async_op + : public operation +{ +public: + // The error code to be passed to the completion handler. + boost::system::error_code ec_; + + // The result of the operation, to be passed to the completion handler. + TResult result_; + +protected: + winrt_async_op(func_type complete_func) + : operation(complete_func), + result_() + { + } +}; + +template <> +class winrt_async_op + : public operation +{ +public: + // The error code to be passed to the completion handler. + boost::system::error_code ec_; + +protected: + winrt_async_op(func_type complete_func) + : operation(complete_func) + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_WINRT_ASYNC_OP_HPP diff --git a/include/boost/asio/detail/winrt_resolve_op.hpp b/include/boost/asio/detail/winrt_resolve_op.hpp new file mode 100644 index 00000000..afbbb735 --- /dev/null +++ b/include/boost/asio/detail/winrt_resolve_op.hpp @@ -0,0 +1,119 @@ +// +// detail/winrt_resolve_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_RESOLVE_OP_HPP +#define BOOST_ASIO_DETAIL_WINRT_RESOLVE_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_resolve_op : + public winrt_async_op< + Windows::Foundation::Collections::IVectorView< + Windows::Networking::EndpointPair^>^> +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_resolve_op); + + typedef typename Protocol::endpoint endpoint_type; + typedef boost::asio::ip::basic_resolver_query query_type; + typedef boost::asio::ip::basic_resolver_iterator iterator_type; + + winrt_resolve_op(const query_type& query, Handler& handler) + : winrt_async_op< + Windows::Foundation::Collections::IVectorView< + Windows::Networking::EndpointPair^>^>( + &winrt_resolve_op::do_complete), + query_(query), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code&, std::size_t) + { + // Take ownership of the operation object. + winrt_resolve_op* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + + iterator_type iterator = iterator_type(); + if (!o->ec_) + { + try + { + iterator = iterator_type::create( + o->result_, o->query_.hints(), + o->query_.host_name(), o->query_.service_name()); + } + catch (Platform::Exception^ e) + { + o->ec_ = boost::system::error_code(e->HResult, + boost::system::system_category()); + } + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2 + handler(o->handler_, o->ec_, iterator); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + query_type query_; + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_RESOLVE_OP_HPP diff --git a/include/boost/asio/detail/winrt_resolver_service.hpp b/include/boost/asio/detail/winrt_resolver_service.hpp new file mode 100644 index 00000000..dd7bf6e2 --- /dev/null +++ b/include/boost/asio/detail/winrt_resolver_service.hpp @@ -0,0 +1,185 @@ +// +// detail/winrt_resolver_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_RESOLVER_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WINRT_RESOLVER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_resolver_service +{ +public: + // The implementation type of the resolver. A cancellation token is used to + // indicate to the asynchronous operation that the operation has been + // cancelled. + typedef socket_ops::shared_cancel_token_type implementation_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The query type. + typedef boost::asio::ip::basic_resolver_query query_type; + + // The iterator type. + typedef boost::asio::ip::basic_resolver_iterator iterator_type; + + // Constructor. + winrt_resolver_service(boost::asio::io_service& io_service) + : io_service_(use_service(io_service)), + async_manager_(use_service(io_service)) + { + } + + // Destructor. + ~winrt_resolver_service() + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Perform any fork-related housekeeping. + void fork_service(boost::asio::io_service::fork_event) + { + } + + // Construct a new resolver implementation. + void construct(implementation_type&) + { + } + + // Destroy a resolver implementation. + void destroy(implementation_type&) + { + } + + // Cancel pending asynchronous operations. + void cancel(implementation_type&) + { + } + + // Resolve a query to a list of entries. + iterator_type resolve(implementation_type&, + const query_type& query, boost::system::error_code& ec) + { + try + { + using namespace Windows::Networking::Sockets; + auto endpoint_pairs = async_manager_.sync( + DatagramSocket::GetEndpointPairsAsync( + winrt_utils::host_name(query.host_name()), + winrt_utils::string(query.service_name())), ec); + + if (ec) + return iterator_type(); + + return iterator_type::create( + endpoint_pairs, query.hints(), + query.host_name(), query.service_name()); + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return iterator_type(); + } + } + + // Asynchronously resolve a query to a list of entries. + template + void async_resolve(implementation_type&, + const query_type& query, Handler& handler) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef winrt_resolve_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + boost_asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(query, handler); + + BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve")); + + try + { + using namespace Windows::Networking::Sockets; + async_manager_.async(DatagramSocket::GetEndpointPairsAsync( + winrt_utils::host_name(query.host_name()), + winrt_utils::string(query.service_name())), p.p); + p.v = p.p = 0; + } + catch (Platform::Exception^ e) + { + p.p->ec_ = boost::system::error_code( + e->HResult, boost::system::system_category()); + io_service_.post_immediate_completion(p.p, is_continuation); + p.v = p.p = 0; + } + } + + // Resolve an endpoint to a list of entries. + iterator_type resolve(implementation_type&, + const endpoint_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return iterator_type(); + } + + // Asynchronously resolve an endpoint to a list of entries. + template + void async_resolve(implementation_type&, + const endpoint_type&, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const iterator_type iterator; + io_service_.get_io_service().post( + detail::bind_handler(handler, ec, iterator)); + } + +private: + io_service_impl& io_service_; + winrt_async_manager& async_manager_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_RESOLVER_SERVICE_HPP diff --git a/include/boost/asio/detail/winrt_socket_connect_op.hpp b/include/boost/asio/detail/winrt_socket_connect_op.hpp new file mode 100644 index 00000000..2cba4dd7 --- /dev/null +++ b/include/boost/asio/detail/winrt_socket_connect_op.hpp @@ -0,0 +1,92 @@ +// +// detail/winrt_socket_connect_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_HPP +#define BOOST_ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_socket_connect_op : + public winrt_async_op +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_connect_op); + + winrt_socket_connect_op(Handler& handler) + : winrt_async_op(&winrt_socket_connect_op::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code&, std::size_t) + { + // Take ownership of the operation object. + winrt_socket_connect_op* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1 + handler(o->handler_, o->ec_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_HPP diff --git a/include/boost/asio/detail/winrt_socket_recv_op.hpp b/include/boost/asio/detail/winrt_socket_recv_op.hpp new file mode 100644 index 00000000..c21ef6b1 --- /dev/null +++ b/include/boost/asio/detail/winrt_socket_recv_op.hpp @@ -0,0 +1,112 @@ +// +// detail/winrt_socket_recv_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_SOCKET_RECV_OP_HPP +#define BOOST_ASIO_DETAIL_WINRT_SOCKET_RECV_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_socket_recv_op : + public winrt_async_op +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_recv_op); + + winrt_socket_recv_op(const MutableBufferSequence& buffers, Handler& handler) + : winrt_async_op( + &winrt_socket_recv_op::do_complete), + buffers_(buffers), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code&, std::size_t) + { + // Take ownership of the operation object. + winrt_socket_recv_op* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + if (owner) + { + buffer_sequence_adapter::validate(o->buffers_); + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + std::size_t bytes_transferred = o->result_ ? o->result_->Length : 0; + if (bytes_transferred == 0 && !o->ec_ && + !buffer_sequence_adapter::all_empty(o->buffers_)) + { + o->ec_ = boost::asio::error::eof; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2 + handler(o->handler_, o->ec_, bytes_transferred); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + MutableBufferSequence buffers_; + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_SOCKET_RECV_OP_HPP diff --git a/include/boost/asio/detail/winrt_socket_send_op.hpp b/include/boost/asio/detail/winrt_socket_send_op.hpp new file mode 100644 index 00000000..19d68739 --- /dev/null +++ b/include/boost/asio/detail/winrt_socket_send_op.hpp @@ -0,0 +1,103 @@ +// +// detail/winrt_socket_send_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_SOCKET_SEND_OP_HPP +#define BOOST_ASIO_DETAIL_WINRT_SOCKET_SEND_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_socket_send_op : + public winrt_async_op +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_send_op); + + winrt_socket_send_op(const ConstBufferSequence& buffers, Handler& handler) + : winrt_async_op(&winrt_socket_send_op::do_complete), + buffers_(buffers), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code&, std::size_t) + { + // Take ownership of the operation object. + winrt_socket_send_op* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + if (owner) + { + buffer_sequence_adapter::validate(o->buffers_); + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2 + handler(o->handler_, o->ec_, o->result_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + ConstBufferSequence buffers_; + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_SOCKET_SEND_OP_HPP diff --git a/include/boost/asio/detail/winrt_ssocket_service.hpp b/include/boost/asio/detail/winrt_ssocket_service.hpp new file mode 100644 index 00000000..d0063cd6 --- /dev/null +++ b/include/boost/asio/detail/winrt_ssocket_service.hpp @@ -0,0 +1,234 @@ +// +// detail/winrt_ssocket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winrt_ssocket_service : + public winrt_ssocket_service_base +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type; + + // The implementation type of the socket. + struct implementation_type : base_implementation_type + { + // Default constructor. + implementation_type() + : base_implementation_type(), + protocol_(endpoint_type().protocol()) + { + } + + // The protocol associated with the socket. + protocol_type protocol_; + }; + + // Constructor. + winrt_ssocket_service(boost::asio::io_service& io_service) + : winrt_ssocket_service_base(io_service) + { + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type& impl, + winrt_ssocket_service& other_service, + implementation_type& other_impl) + { + this->base_move_assign(impl, other_service, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-construct a new socket implementation from another protocol type. + template + void converting_move_construct(implementation_type& impl, + typename winrt_ssocket_service< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + try + { + impl.socket_ = ref new Windows::Networking::Sockets::StreamSocket; + impl.protocol_ = protocol; + ec = boost::system::error_code(); + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + } + + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + impl.socket_ = native_socket; + impl.protocol_ = protocol; + ec = boost::system::error_code(); + + return ec; + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type&, + const endpoint_type&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + endpoint.resize(do_get_endpoint(impl, true, + endpoint.data(), endpoint.size(), ec)); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + endpoint.resize(do_get_endpoint(impl, false, + endpoint.data(), endpoint.size(), ec)); + return endpoint; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + return do_set_option(impl, option.level(impl.protocol_), + option.name(impl.protocol_), option.data(impl.protocol_), + option.size(impl.protocol_), ec); + } + + // Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + std::size_t size = option.size(impl.protocol_); + do_get_option(impl, option.level(impl.protocol_), + option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return do_connect(impl, peer_endpoint.data(), ec); + } + + // Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, Handler& handler) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef winrt_socket_connect_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + boost_asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect")); + + start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP diff --git a/include/boost/asio/detail/winrt_ssocket_service_base.hpp b/include/boost/asio/detail/winrt_ssocket_service_base.hpp new file mode 100644 index 00000000..caaf98b7 --- /dev/null +++ b/include/boost/asio/detail/winrt_ssocket_service_base.hpp @@ -0,0 +1,357 @@ +// +// detail/winrt_ssocket_service_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP +#define BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class winrt_ssocket_service_base +{ +public: + // The native type of a socket. + typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type; + + // The implementation type of the socket. + struct base_implementation_type + { + // Default constructor. + base_implementation_type() + : socket_(nullptr), + next_(0), + prev_(0) + { + } + + // The underlying native socket. + native_handle_type socket_; + + // Pointers to adjacent socket implementations in linked list. + base_implementation_type* next_; + base_implementation_type* prev_; + }; + + // Constructor. + BOOST_ASIO_DECL winrt_ssocket_service_base( + boost::asio::io_service& io_service); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void shutdown_service(); + + // Construct a new socket implementation. + BOOST_ASIO_DECL void construct(base_implementation_type&); + + // Move-construct a new socket implementation. + BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, + base_implementation_type& other_impl); + + // Move-assign from another socket implementation. + BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, + winrt_ssocket_service_base& other_service, + base_implementation_type& other_impl); + + // Destroy a socket implementation. + BOOST_ASIO_DECL void destroy(base_implementation_type& impl); + + // Determine whether the socket is open. + bool is_open(const base_implementation_type& impl) const + { + return impl.socket_ != nullptr; + } + + // Destroy a socket implementation. + BOOST_ASIO_DECL boost::system::error_code close( + base_implementation_type& impl, boost::system::error_code& ec); + + // Get the native socket representation. + native_handle_type native_handle(base_implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + boost::system::error_code cancel(base_implementation_type&, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const base_implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return false; + } + + // Determine the number of bytes available for reading. + std::size_t available(const base_implementation_type&, + boost::system::error_code& ec) const + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(base_implementation_type&, + IO_Control_Command&, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const base_implementation_type&) const + { + return false; + } + + // Sets the non-blocking mode of the socket. + boost::system::error_code non_blocking(base_implementation_type&, + bool, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const base_implementation_type&) const + { + return false; + } + + // Sets the non-blocking mode of the native socket implementation. + boost::system::error_code native_non_blocking(base_implementation_type&, + bool, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Disable sends or receives on the socket. + boost::system::error_code shutdown(base_implementation_type&, + socket_base::shutdown_type, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Send the given data to the peer. + template + std::size_t send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return do_send(impl, + buffer_sequence_adapter::first(buffers), flags, ec); + } + + // Wait until data can be sent without blocking. + std::size_t send(base_implementation_type&, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef winrt_socket_send_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + boost_asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(buffers, handler); + + BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send")); + + start_send_op(impl, + buffer_sequence_adapter::first(buffers), + flags, p.p, is_continuation); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(base_implementation_type&, const null_buffers&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.get_io_service().post( + detail::bind_handler(handler, ec, bytes_transferred)); + } + + // Receive some data from the peer. Returns the number of bytes received. + template + std::size_t receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return do_receive(impl, + buffer_sequence_adapter::first(buffers), flags, ec); + } + + // Wait until data can be received without blocking. + std::size_t receive(base_implementation_type&, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef winrt_socket_recv_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + boost_asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(buffers, handler); + + BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive")); + + start_receive_op(impl, + buffer_sequence_adapter::first(buffers), + flags, p.p, is_continuation); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive(base_implementation_type&, const null_buffers&, + socket_base::message_flags, Handler& handler) + { + boost::system::error_code ec = boost::asio::error::operation_not_supported; + const std::size_t bytes_transferred = 0; + io_service_.get_io_service().post( + detail::bind_handler(handler, ec, bytes_transferred)); + } + +protected: + // Helper function to obtain endpoints associated with the connection. + BOOST_ASIO_DECL std::size_t do_get_endpoint( + const base_implementation_type& impl, bool local, + void* addr, std::size_t addr_len, boost::system::error_code& ec) const; + + // Helper function to set a socket option. + BOOST_ASIO_DECL boost::system::error_code do_set_option( + base_implementation_type& impl, + int level, int optname, const void* optval, + std::size_t optlen, boost::system::error_code& ec); + + // Helper function to get a socket option. + BOOST_ASIO_DECL void do_get_option( + const base_implementation_type& impl, + int level, int optname, void* optval, + std::size_t* optlen, boost::system::error_code& ec) const; + + // Helper function to perform a synchronous connect. + BOOST_ASIO_DECL boost::system::error_code do_connect( + base_implementation_type& impl, + const void* addr, boost::system::error_code& ec); + + // Helper function to start an asynchronous connect. + BOOST_ASIO_DECL void start_connect_op( + base_implementation_type& impl, const void* addr, + winrt_async_op* op, bool is_continuation); + + // Helper function to perform a synchronous send. + BOOST_ASIO_DECL std::size_t do_send( + base_implementation_type& impl, const boost::asio::const_buffer& data, + socket_base::message_flags flags, boost::system::error_code& ec); + + // Helper function to start an asynchronous send. + BOOST_ASIO_DECL void start_send_op(base_implementation_type& impl, + const boost::asio::const_buffer& data, socket_base::message_flags flags, + winrt_async_op* op, bool is_continuation); + + // Helper function to perform a synchronous receive. + BOOST_ASIO_DECL std::size_t do_receive( + base_implementation_type& impl, const boost::asio::mutable_buffer& data, + socket_base::message_flags flags, boost::system::error_code& ec); + + // Helper function to start an asynchronous receive. + BOOST_ASIO_DECL void start_receive_op(base_implementation_type& impl, + const boost::asio::mutable_buffer& data, socket_base::message_flags flags, + winrt_async_op* op, + bool is_continuation); + + // The io_service implementation used for delivering completions. + io_service_impl& io_service_; + + // The manager that keeps track of outstanding operations. + winrt_async_manager& async_manager_; + + // Mutex to protect access to the linked list of implementations. + boost::asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + base_implementation_type* impl_list_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP diff --git a/include/boost/asio/detail/winrt_timer_scheduler.hpp b/include/boost/asio/detail/winrt_timer_scheduler.hpp new file mode 100644 index 00000000..0650eeea --- /dev/null +++ b/include/boost/asio/detail/winrt_timer_scheduler.hpp @@ -0,0 +1,133 @@ +// +// detail/winrt_timer_scheduler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_TIMER_SCHEDULER_HPP +#define BOOST_ASIO_DETAIL_WINRT_TIMER_SCHEDULER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_IOCP) +# include +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class winrt_timer_scheduler + : public boost::asio::detail::service_base +{ +public: + // Constructor. + BOOST_ASIO_DECL winrt_timer_scheduler(boost::asio::io_service& io_service); + + // Destructor. + BOOST_ASIO_DECL ~winrt_timer_scheduler(); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void shutdown_service(); + + // Recreate internal descriptors following a fork. + BOOST_ASIO_DECL void fork_service( + boost::asio::io_service::fork_event fork_ev); + + // Initialise the task. No effect as this class uses its own thread. + BOOST_ASIO_DECL void init_task(); + + // Add a new timer queue to the reactor. + template + void add_timer_queue(timer_queue& queue); + + // Remove a timer queue from the reactor. + template + void remove_timer_queue(timer_queue& queue); + + // Schedule a new operation in the given timer queue to expire at the + // specified absolute time. + template + void schedule_timer(timer_queue& queue, + const typename Time_Traits::time_type& time, + typename timer_queue::per_timer_data& timer, wait_op* op); + + // Cancel the timer operations associated with the given token. Returns the + // number of operations that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& queue, + typename timer_queue::per_timer_data& timer, + std::size_t max_cancelled = (std::numeric_limits::max)()); + +private: + // Run the select loop in the thread. + BOOST_ASIO_DECL void run_thread(); + + // Entry point for the select loop thread. + BOOST_ASIO_DECL static void call_run_thread(winrt_timer_scheduler* reactor); + + // Helper function to add a new timer queue. + BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); + + // Helper function to remove a timer queue. + BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); + + // The io_service implementation used to post completions. + io_service_impl& io_service_; + + // Mutex used to protect internal variables. + boost::asio::detail::mutex mutex_; + + // Event used to wake up background thread. + boost::asio::detail::event event_; + + // The timer queues. + timer_queue_set timer_queues_; + + // The background thread that is waiting for timers to expire. + boost::asio::detail::thread* thread_; + + // Does the background thread need to stop. + bool stop_thread_; + + // Whether the service has been shut down. + bool shutdown_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#include +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_TIMER_SCHEDULER_HPP diff --git a/include/boost/asio/detail/winrt_utils.hpp b/include/boost/asio/detail/winrt_utils.hpp new file mode 100644 index 00000000..ba034bcd --- /dev/null +++ b/include/boost/asio/detail/winrt_utils.hpp @@ -0,0 +1,108 @@ +// +// detail/winrt_utils.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINRT_UTILS_HPP +#define BOOST_ASIO_DETAIL_WINRT_UTILS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace winrt_utils { + +inline Platform::String^ string(const char* from) +{ + std::wstring tmp(from, from + std::strlen(from)); + return ref new Platform::String(tmp.c_str()); +} + +inline Platform::String^ string(const std::string& from) +{ + std::wstring tmp(from.begin(), from.end()); + return ref new Platform::String(tmp.c_str()); +} + +inline std::string string(Platform::String^ from) +{ + std::wstring_convert> converter; + return converter.to_bytes(from->Data()); +} + +inline Platform::String^ string(unsigned short from) +{ + return string(std::to_string(from)); +} + +template +inline Platform::String^ string(const T& from) +{ + return string(from.to_string()); +} + +inline int integer(Platform::String^ from) +{ + return _wtoi(from->Data()); +} + +template +inline Windows::Networking::HostName^ host_name(const T& from) +{ + return ref new Windows::Networking::HostName((string)(from)); +} + +template +inline Windows::Storage::Streams::IBuffer^ buffer_dup( + const ConstBufferSequence& buffers) +{ + using Microsoft::WRL::ComPtr; + std::size_t size = boost::asio::buffer_size(buffers); + auto b = ref new Windows::Storage::Streams::Buffer(size); + ComPtr insp = reinterpret_cast(b); + ComPtr bacc; + insp.As(&bacc); + byte* bytes = nullptr; + bacc->Buffer(&bytes); + boost::asio::buffer_copy(boost::asio::buffer(bytes, size), buffers); + b->Length = size; + return b; +} + +} // namespace winrt_utils +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_WINRT_UTILS_HPP diff --git a/include/boost/asio/detail/wrapped_handler.hpp b/include/boost/asio/detail/wrapped_handler.hpp index b80e11b1..ad1d0512 100644 --- a/include/boost/asio/detail/wrapped_handler.hpp +++ b/include/boost/asio/detail/wrapped_handler.hpp @@ -73,7 +73,7 @@ public: void operator()() { - dispatcher_.dispatch(handler_); + dispatcher_.dispatch(BOOST_ASIO_MOVE_CAST(Handler)(handler_)); } void operator()() const diff --git a/include/boost/asio/error.hpp b/include/boost/asio/error.hpp index a303e57a..6ff5d1c4 100644 --- a/include/boost/asio/error.hpp +++ b/include/boost/asio/error.hpp @@ -18,7 +18,9 @@ #include #include #include -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) # include #else # include @@ -36,6 +38,12 @@ # define BOOST_ASIO_GETADDRINFO_ERROR(e) implementation_defined /// INTERNAL ONLY. # define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) +# define BOOST_ASIO_NATIVE_ERROR(e) __HRESULT_FROM_WIN32(e) +# define BOOST_ASIO_SOCKET_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e) +# define BOOST_ASIO_NETDB_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e) +# define BOOST_ASIO_GETADDRINFO_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e) +# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) e_win #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) # define BOOST_ASIO_NATIVE_ERROR(e) e # define BOOST_ASIO_SOCKET_ERROR(e) WSA ## e diff --git a/include/boost/asio/generic/datagram_protocol.hpp b/include/boost/asio/generic/datagram_protocol.hpp index 01539cb7..87d81b4c 100644 --- a/include/boost/asio/generic/datagram_protocol.hpp +++ b/include/boost/asio/generic/datagram_protocol.hpp @@ -76,7 +76,7 @@ public: /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_DGRAM; + return BOOST_ASIO_OS_DEF(SOCK_DGRAM); } /// Obtain an identifier for the protocol. diff --git a/include/boost/asio/generic/raw_protocol.hpp b/include/boost/asio/generic/raw_protocol.hpp index 0097e329..4dfe9b00 100644 --- a/include/boost/asio/generic/raw_protocol.hpp +++ b/include/boost/asio/generic/raw_protocol.hpp @@ -76,7 +76,7 @@ public: /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_RAW; + return BOOST_ASIO_OS_DEF(SOCK_RAW); } /// Obtain an identifier for the protocol. diff --git a/include/boost/asio/generic/seq_packet_protocol.hpp b/include/boost/asio/generic/seq_packet_protocol.hpp index 935596b9..bc48991f 100644 --- a/include/boost/asio/generic/seq_packet_protocol.hpp +++ b/include/boost/asio/generic/seq_packet_protocol.hpp @@ -75,7 +75,7 @@ public: /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_SEQPACKET; + return BOOST_ASIO_OS_DEF(SOCK_SEQPACKET); } /// Obtain an identifier for the protocol. diff --git a/include/boost/asio/generic/stream_protocol.hpp b/include/boost/asio/generic/stream_protocol.hpp index c14cb7f6..20eefe78 100644 --- a/include/boost/asio/generic/stream_protocol.hpp +++ b/include/boost/asio/generic/stream_protocol.hpp @@ -77,7 +77,7 @@ public: /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_STREAM; + return BOOST_ASIO_OS_DEF(SOCK_STREAM); } /// Obtain an identifier for the protocol. diff --git a/include/boost/asio/handler_invoke_hook.hpp b/include/boost/asio/handler_invoke_hook.hpp index 8db36b38..5f81845c 100644 --- a/include/boost/asio/handler_invoke_hook.hpp +++ b/include/boost/asio/handler_invoke_hook.hpp @@ -22,8 +22,10 @@ namespace boost { namespace asio { -/// Default invoke function for handlers. -/** +/** @defgroup asio_handler_invoke boost::asio::asio_handler_invoke + * + * @brief Default invoke function for handlers. + * * Completion handlers for asynchronous operations are invoked by the * io_service associated with the corresponding object (e.g. a socket or * deadline_timer). Certain guarantees are made on when the handler may be @@ -42,10 +44,10 @@ namespace asio { * Implement asio_handler_invoke for your own handlers to specify a custom * invocation strategy. * - * This default implementation is simply: - * @code - * function(); - * @endcode + * This default implementation invokes the function object like so: + * @code function(); @endcode + * If necessary, the default implementation makes a copy of the function object + * so that the non-const operator() can be used. * * @par Example * @code @@ -58,12 +60,25 @@ namespace asio { * } * @endcode */ +/*@{*/ + +/// Default handler invocation hook used for non-const function objects. template -inline void asio_handler_invoke(Function function, ...) +inline void asio_handler_invoke(Function& function, ...) { function(); } +/// Default handler invocation hook used for const function objects. +template +inline void asio_handler_invoke(const Function& function, ...) +{ + Function tmp(function); + tmp(); +} + +/*@}*/ + } // namespace asio } // namespace boost diff --git a/include/boost/asio/impl/buffered_read_stream.hpp b/include/boost/asio/impl/buffered_read_stream.hpp new file mode 100644 index 00000000..5d69555e --- /dev/null +++ b/include/boost/asio/impl/buffered_read_stream.hpp @@ -0,0 +1,360 @@ +// +// impl/buffered_read_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP +#define BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +template +std::size_t buffered_read_stream::fill() +{ + detail::buffer_resize_guard + resize_guard(storage_); + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + storage_.resize(previous_size + next_layer_.read_some(buffer( + storage_.data() + previous_size, + storage_.size() - previous_size))); + resize_guard.commit(); + return storage_.size() - previous_size; +} + +template +std::size_t buffered_read_stream::fill(boost::system::error_code& ec) +{ + detail::buffer_resize_guard + resize_guard(storage_); + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + storage_.resize(previous_size + next_layer_.read_some(buffer( + storage_.data() + previous_size, + storage_.size() - previous_size), + ec)); + resize_guard.commit(); + return storage_.size() - previous_size; +} + +namespace detail +{ + template + class buffered_fill_handler + { + public: + buffered_fill_handler(detail::buffered_stream_storage& storage, + std::size_t previous_size, ReadHandler& handler) + : storage_(storage), + previous_size_(previous_size), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + buffered_fill_handler(const buffered_fill_handler& other) + : storage_(other.storage_), + previous_size_(other.previous_size_), + handler_(other.handler_) + { + } + + buffered_fill_handler(buffered_fill_handler&& other) + : storage_(other.storage_), + previous_size_(other.previous_size_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + const std::size_t bytes_transferred) + { + storage_.resize(previous_size_ + bytes_transferred); + handler_(ec, bytes_transferred); + } + + //private: + detail::buffered_stream_storage& storage_; + std::size_t previous_size_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + buffered_fill_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + buffered_fill_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template + inline bool asio_handler_is_continuation( + buffered_fill_handler* this_handler) + { + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template + inline void asio_handler_invoke(Function& function, + buffered_fill_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + buffered_fill_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template +template +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +buffered_read_stream::async_fill( + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + next_layer_.async_read_some( + buffer( + storage_.data() + previous_size, + storage_.size() - previous_size), + detail::buffered_fill_handler( + storage_, previous_size, init.handler)); + + return init.result.get(); +} + +template +template +std::size_t buffered_read_stream::read_some( + const MutableBufferSequence& buffers) +{ + if (boost::asio::buffer_size(buffers) == 0) + return 0; + + if (storage_.empty()) + this->fill(); + + return this->copy(buffers); +} + +template +template +std::size_t buffered_read_stream::read_some( + const MutableBufferSequence& buffers, boost::system::error_code& ec) +{ + ec = boost::system::error_code(); + + if (boost::asio::buffer_size(buffers) == 0) + return 0; + + if (storage_.empty() && !this->fill(ec)) + return 0; + + return this->copy(buffers); +} + +namespace detail +{ + template + class buffered_read_some_handler + { + public: + buffered_read_some_handler(detail::buffered_stream_storage& storage, + const MutableBufferSequence& buffers, ReadHandler& handler) + : storage_(storage), + buffers_(buffers), + handler_(handler) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + buffered_read_some_handler(const buffered_read_some_handler& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(other.handler_) + { + } + + buffered_read_some_handler(buffered_read_some_handler&& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, std::size_t) + { + if (ec || storage_.empty()) + { + const std::size_t length = 0; + handler_(ec, length); + } + else + { + const std::size_t bytes_copied = boost::asio::buffer_copy( + buffers_, storage_.data(), storage_.size()); + storage_.consume(bytes_copied); + handler_(ec, bytes_copied); + } + } + + //private: + detail::buffered_stream_storage& storage_; + MutableBufferSequence buffers_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + buffered_read_some_handler< + MutableBufferSequence, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + buffered_read_some_handler< + MutableBufferSequence, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template + inline bool asio_handler_is_continuation( + buffered_read_some_handler< + MutableBufferSequence, ReadHandler>* this_handler) + { + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template + inline void asio_handler_invoke(Function& function, + buffered_read_some_handler< + MutableBufferSequence, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + buffered_read_some_handler< + MutableBufferSequence, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template +template +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +buffered_read_stream::async_read_some( + const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + if (boost::asio::buffer_size(buffers) == 0 || !storage_.empty()) + { + next_layer_.async_read_some(boost::asio::mutable_buffers_1(0, 0), + detail::buffered_read_some_handler< + MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void (boost::system::error_code, std::size_t))>( + storage_, buffers, init.handler)); + } + else + { + this->async_fill(detail::buffered_read_some_handler< + MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void (boost::system::error_code, std::size_t))>( + storage_, buffers, init.handler)); + } + + return init.result.get(); +} + +template +template +std::size_t buffered_read_stream::peek( + const MutableBufferSequence& buffers) +{ + if (storage_.empty()) + this->fill(); + return this->peek_copy(buffers); +} + +template +template +std::size_t buffered_read_stream::peek( + const MutableBufferSequence& buffers, boost::system::error_code& ec) +{ + ec = boost::system::error_code(); + if (storage_.empty() && !this->fill(ec)) + return 0; + return this->peek_copy(buffers); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP diff --git a/include/boost/asio/impl/buffered_write_stream.hpp b/include/boost/asio/impl/buffered_write_stream.hpp new file mode 100644 index 00000000..6f909c6e --- /dev/null +++ b/include/boost/asio/impl/buffered_write_stream.hpp @@ -0,0 +1,340 @@ +// +// impl/buffered_write_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP +#define BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +template +std::size_t buffered_write_stream::flush() +{ + std::size_t bytes_written = write(next_layer_, + buffer(storage_.data(), storage_.size())); + storage_.consume(bytes_written); + return bytes_written; +} + +template +std::size_t buffered_write_stream::flush(boost::system::error_code& ec) +{ + std::size_t bytes_written = write(next_layer_, + buffer(storage_.data(), storage_.size()), + transfer_all(), ec); + storage_.consume(bytes_written); + return bytes_written; +} + +namespace detail +{ + template + class buffered_flush_handler + { + public: + buffered_flush_handler(detail::buffered_stream_storage& storage, + WriteHandler& handler) + : storage_(storage), + handler_(handler) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + buffered_flush_handler(const buffered_flush_handler& other) + : storage_(other.storage_), + handler_(other.handler_) + { + } + + buffered_flush_handler(buffered_flush_handler&& other) + : storage_(other.storage_), + handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + const std::size_t bytes_written) + { + storage_.consume(bytes_written); + handler_(ec, bytes_written); + } + + //private: + detail::buffered_stream_storage& storage_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + buffered_flush_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + buffered_flush_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template + inline bool asio_handler_is_continuation( + buffered_flush_handler* this_handler) + { + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template + inline void asio_handler_invoke(Function& function, + buffered_flush_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + buffered_flush_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} + +template +template +BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +buffered_write_stream::async_flush( + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + async_write(next_layer_, buffer(storage_.data(), storage_.size()), + detail::buffered_flush_handler( + storage_, init.handler)); + + return init.result.get(); +} + +template +template +std::size_t buffered_write_stream::write_some( + const ConstBufferSequence& buffers) +{ + if (boost::asio::buffer_size(buffers) == 0) + return 0; + + if (storage_.size() == storage_.capacity()) + this->flush(); + + return this->copy(buffers); +} + +template +template +std::size_t buffered_write_stream::write_some( + const ConstBufferSequence& buffers, boost::system::error_code& ec) +{ + ec = boost::system::error_code(); + + if (boost::asio::buffer_size(buffers) == 0) + return 0; + + if (storage_.size() == storage_.capacity() && !flush(ec)) + return 0; + + return this->copy(buffers); +} + +namespace detail +{ + template + class buffered_write_some_handler + { + public: + buffered_write_some_handler(detail::buffered_stream_storage& storage, + const ConstBufferSequence& buffers, WriteHandler& handler) + : storage_(storage), + buffers_(buffers), + handler_(handler) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + buffered_write_some_handler(const buffered_write_some_handler& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(other.handler_) + { + } + + buffered_write_some_handler(buffered_write_some_handler&& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, std::size_t) + { + if (ec) + { + const std::size_t length = 0; + handler_(ec, length); + } + else + { + std::size_t orig_size = storage_.size(); + std::size_t space_avail = storage_.capacity() - orig_size; + std::size_t bytes_avail = boost::asio::buffer_size(buffers_); + std::size_t length = bytes_avail < space_avail + ? bytes_avail : space_avail; + storage_.resize(orig_size + length); + const std::size_t bytes_copied = boost::asio::buffer_copy( + storage_.data() + orig_size, buffers_, length); + handler_(ec, bytes_copied); + } + } + + //private: + detail::buffered_stream_storage& storage_; + ConstBufferSequence buffers_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + buffered_write_some_handler< + ConstBufferSequence, WriteHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + buffered_write_some_handler< + ConstBufferSequence, WriteHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template + inline bool asio_handler_is_continuation( + buffered_write_some_handler< + ConstBufferSequence, WriteHandler>* this_handler) + { + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template + inline void asio_handler_invoke(Function& function, + buffered_write_some_handler< + ConstBufferSequence, WriteHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + buffered_write_some_handler< + ConstBufferSequence, WriteHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template +template +BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +buffered_write_stream::async_write_some( + const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + if (boost::asio::buffer_size(buffers) == 0 + || storage_.size() < storage_.capacity()) + { + next_layer_.async_write_some(boost::asio::const_buffers_1(0, 0), + detail::buffered_write_some_handler< + ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE( + WriteHandler, void (boost::system::error_code, std::size_t))>( + storage_, buffers, init.handler)); + } + else + { + this->async_flush(detail::buffered_write_some_handler< + ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE( + WriteHandler, void (boost::system::error_code, std::size_t))>( + storage_, buffers, init.handler)); + } + + return init.result.get(); +} + +template +template +std::size_t buffered_write_stream::copy( + const ConstBufferSequence& buffers) +{ + std::size_t orig_size = storage_.size(); + std::size_t space_avail = storage_.capacity() - orig_size; + std::size_t bytes_avail = boost::asio::buffer_size(buffers); + std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail; + storage_.resize(orig_size + length); + return boost::asio::buffer_copy( + storage_.data() + orig_size, buffers, length); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP diff --git a/include/boost/asio/impl/handler_alloc_hook.ipp b/include/boost/asio/impl/handler_alloc_hook.ipp index b781c1c5..afbf2b79 100644 --- a/include/boost/asio/impl/handler_alloc_hook.ipp +++ b/include/boost/asio/impl/handler_alloc_hook.ipp @@ -21,7 +21,6 @@ #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) # if defined(BOOST_ASIO_HAS_IOCP) -# include # include # else // defined(BOOST_ASIO_HAS_IOCP) # include @@ -33,6 +32,10 @@ namespace boost { namespace asio { +#if defined(BOOST_ASIO_HAS_IOCP) +namespace detail { class win_iocp_io_service; } +#endif // defined(BOOST_ASIO_HAS_IOCP) + void* asio_handler_allocate(std::size_t size, ...) { #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) diff --git a/include/boost/asio/impl/serial_port_base.ipp b/include/boost/asio/impl/serial_port_base.ipp index 8569ef0c..2d8d35eb 100644 --- a/include/boost/asio/impl/serial_port_base.ipp +++ b/include/boost/asio/impl/serial_port_base.ipp @@ -111,7 +111,6 @@ boost::system::error_code serial_port_base::baud_rate::store( case 4000000: baud = B4000000; break; # endif default: - baud = B0; ec = boost::asio::error::invalid_argument; return ec; } diff --git a/include/boost/asio/impl/src.hpp b/include/boost/asio/impl/src.hpp index bf6a6b57..b111ce1c 100644 --- a/include/boost/asio/impl/src.hpp +++ b/include/boost/asio/impl/src.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/include/boost/asio/io_service.hpp b/include/boost/asio/io_service.hpp index 7148a898..4672c039 100644 --- a/include/boost/asio/io_service.hpp +++ b/include/boost/asio/io_service.hpp @@ -21,16 +21,9 @@ #include #include #include -#include #include #include -#if defined(BOOST_ASIO_HAS_IOCP) -# include -#else -# include -#endif - #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) # include #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ @@ -48,11 +41,15 @@ template Service& use_service(io_service& ios); template void add_service(io_service& ios, Service* svc); template bool has_service(io_service& ios); +namespace detail { #if defined(BOOST_ASIO_HAS_IOCP) -namespace detail { typedef win_iocp_io_service io_service_impl; } + typedef class win_iocp_io_service io_service_impl; + class win_iocp_overlapped_ptr; #else -namespace detail { typedef task_io_service io_service_impl; } + typedef class task_io_service io_service_impl; #endif + class service_registry; +} // namespace detail /// Provides core I/O functionality. /** diff --git a/include/boost/asio/ip/basic_resolver_iterator.hpp b/include/boost/asio/ip/basic_resolver_iterator.hpp index 2046439a..509fba14 100644 --- a/include/boost/asio/ip/basic_resolver_iterator.hpp +++ b/include/boost/asio/ip/basic_resolver_iterator.hpp @@ -26,6 +26,10 @@ #include #include +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + #include namespace boost { @@ -86,8 +90,8 @@ public: while (address_info) { - if (address_info->ai_family == PF_INET - || address_info->ai_family == PF_INET6) + if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET) + || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6)) { using namespace std; // For memcpy. typename InternetProtocol::endpoint endpoint; @@ -117,6 +121,67 @@ public: return iter; } + /// Create an iterator from a sequence of endpoints, host and service name. + template + static basic_resolver_iterator create( + EndpointIterator begin, EndpointIterator end, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + if (begin != end) + { + iter.values_.reset(new values_type); + for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) + { + iter.values_->push_back( + basic_resolver_entry( + *ep_iter, host_name, service_name)); + } + } + return iter; + } + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + /// Create an iterator from a Windows Runtime list of EndpointPair objects. + static basic_resolver_iterator create( + Windows::Foundation::Collections::IVectorView< + Windows::Networking::EndpointPair^>^ endpoints, + const boost::asio::detail::addrinfo_type& hints, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + if (endpoints->Size) + { + iter.values_.reset(new values_type); + for (unsigned int i = 0; i < endpoints->Size; ++i) + { + auto pair = endpoints->GetAt(i); + + if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET) + && pair->RemoteHostName->Type + != Windows::Networking::HostNameType::Ipv4) + continue; + + if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6) + && pair->RemoteHostName->Type + != Windows::Networking::HostNameType::Ipv6) + continue; + + iter.values_->push_back( + basic_resolver_entry( + typename InternetProtocol::endpoint( + ip::address::from_string( + boost::asio::detail::winrt_utils::string( + pair->RemoteHostName->CanonicalName)), + boost::asio::detail::winrt_utils::integer( + pair->RemoteServiceName)), + host_name, service_name)); + } + } + return iter; + } +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + /// Dereference an iterator. const basic_resolver_entry& operator*() const { diff --git a/include/boost/asio/ip/basic_resolver_query.hpp b/include/boost/asio/ip/basic_resolver_query.hpp index ec21e0f5..f25fd1ea 100644 --- a/include/boost/asio/ip/basic_resolver_query.hpp +++ b/include/boost/asio/ip/basic_resolver_query.hpp @@ -153,7 +153,7 @@ public: { typename InternetProtocol::endpoint endpoint; hints_.ai_flags = static_cast(resolve_flags); - hints_.ai_family = PF_UNSPEC; + hints_.ai_family = BOOST_ASIO_OS_DEF(AF_UNSPEC); hints_.ai_socktype = endpoint.protocol().type(); hints_.ai_protocol = endpoint.protocol().protocol(); hints_.ai_addrlen = 0; diff --git a/include/boost/asio/ip/detail/endpoint.hpp b/include/boost/asio/ip/detail/endpoint.hpp index e6d60136..94c85775 100644 --- a/include/boost/asio/ip/detail/endpoint.hpp +++ b/include/boost/asio/ip/detail/endpoint.hpp @@ -109,7 +109,7 @@ public: // Determine whether the endpoint is IPv4. bool is_v4() const { - return data_.base.sa_family == AF_INET; + return data_.base.sa_family == BOOST_ASIO_OS_DEF(AF_INET); } #if !defined(BOOST_ASIO_NO_IOSTREAM) diff --git a/include/boost/asio/ip/detail/impl/endpoint.ipp b/include/boost/asio/ip/detail/impl/endpoint.ipp index 6be3d237..52857659 100644 --- a/include/boost/asio/ip/detail/impl/endpoint.ipp +++ b/include/boost/asio/ip/detail/impl/endpoint.ipp @@ -35,25 +35,25 @@ namespace detail { endpoint::endpoint() : data_() { - data_.v4.sin_family = AF_INET; + data_.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); data_.v4.sin_port = 0; - data_.v4.sin_addr.s_addr = INADDR_ANY; + data_.v4.sin_addr.s_addr = BOOST_ASIO_OS_DEF(INADDR_ANY); } endpoint::endpoint(int family, unsigned short port_num) : data_() { using namespace std; // For memcpy. - if (family == PF_INET) + if (family == BOOST_ASIO_OS_DEF(AF_INET)) { - data_.v4.sin_family = AF_INET; + data_.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); data_.v4.sin_port = boost::asio::detail::socket_ops::host_to_network_short(port_num); - data_.v4.sin_addr.s_addr = INADDR_ANY; + data_.v4.sin_addr.s_addr = BOOST_ASIO_OS_DEF(INADDR_ANY); } else { - data_.v6.sin6_family = AF_INET6; + data_.v6.sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); data_.v6.sin6_port = boost::asio::detail::socket_ops::host_to_network_short(port_num); data_.v6.sin6_flowinfo = 0; @@ -76,7 +76,7 @@ endpoint::endpoint(const boost::asio::ip::address& addr, using namespace std; // For memcpy. if (addr.is_v4()) { - data_.v4.sin_family = AF_INET; + data_.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); data_.v4.sin_port = boost::asio::detail::socket_ops::host_to_network_short(port_num); data_.v4.sin_addr.s_addr = @@ -86,7 +86,7 @@ endpoint::endpoint(const boost::asio::ip::address& addr, } else { - data_.v6.sin6_family = AF_INET6; + data_.v6.sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); data_.v6.sin6_port = boost::asio::detail::socket_ops::host_to_network_short(port_num); data_.v6.sin6_flowinfo = 0; diff --git a/include/boost/asio/ip/icmp.hpp b/include/boost/asio/ip/icmp.hpp index fa2ff33e..6f234931 100644 --- a/include/boost/asio/ip/icmp.hpp +++ b/include/boost/asio/ip/icmp.hpp @@ -49,19 +49,21 @@ public: /// Construct to represent the IPv4 ICMP protocol. static icmp v4() { - return icmp(IPPROTO_ICMP, PF_INET); + return icmp(BOOST_ASIO_OS_DEF(IPPROTO_ICMP), + BOOST_ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 ICMP protocol. static icmp v6() { - return icmp(IPPROTO_ICMPV6, PF_INET6); + return icmp(BOOST_ASIO_OS_DEF(IPPROTO_ICMPV6), + BOOST_ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_RAW; + return BOOST_ASIO_OS_DEF(SOCK_RAW); } /// Obtain an identifier for the protocol. diff --git a/include/boost/asio/ip/impl/address_v4.ipp b/include/boost/asio/ip/impl/address_v4.ipp index 5e56fdce..989304aa 100644 --- a/include/boost/asio/ip/impl/address_v4.ipp +++ b/include/boost/asio/ip/impl/address_v4.ipp @@ -88,7 +88,8 @@ std::string address_v4::to_string(boost::system::error_code& ec) const { char addr_str[boost::asio::detail::max_addr_v4_str_len]; const char* addr = - boost::asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str, + boost::asio::detail::socket_ops::inet_ntop( + BOOST_ASIO_OS_DEF(AF_INET), &addr_, addr_str, boost::asio::detail::max_addr_v4_str_len, 0, ec); if (addr == 0) return std::string(); @@ -108,7 +109,7 @@ address_v4 address_v4::from_string( { address_v4 tmp; if (boost::asio::detail::socket_ops::inet_pton( - AF_INET, str, &tmp.addr_, 0, ec) <= 0) + BOOST_ASIO_OS_DEF(AF_INET), str, &tmp.addr_, 0, ec) <= 0) return address_v4(); return tmp; } diff --git a/include/boost/asio/ip/impl/address_v6.ipp b/include/boost/asio/ip/impl/address_v6.ipp index e489e0c8..f2936dfa 100644 --- a/include/boost/asio/ip/impl/address_v6.ipp +++ b/include/boost/asio/ip/impl/address_v6.ipp @@ -110,7 +110,8 @@ std::string address_v6::to_string(boost::system::error_code& ec) const { char addr_str[boost::asio::detail::max_addr_v6_str_len]; const char* addr = - boost::asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str, + boost::asio::detail::socket_ops::inet_ntop( + BOOST_ASIO_OS_DEF(AF_INET6), &addr_, addr_str, boost::asio::detail::max_addr_v6_str_len, scope_id_, ec); if (addr == 0) return std::string(); @@ -130,7 +131,7 @@ address_v6 address_v6::from_string( { address_v6 tmp; if (boost::asio::detail::socket_ops::inet_pton( - AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) + BOOST_ASIO_OS_DEF(AF_INET6), str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) return address_v6(); return tmp; } diff --git a/include/boost/asio/ip/multicast.hpp b/include/boost/asio/ip/multicast.hpp index 6b687ac5..cd5c6046 100644 --- a/include/boost/asio/ip/multicast.hpp +++ b/include/boost/asio/ip/multicast.hpp @@ -48,7 +48,10 @@ namespace multicast { typedef implementation_defined join_group; #else typedef boost::asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_ADD_MEMBERSHIP, IPPROTO_IPV6, IPV6_JOIN_GROUP> join_group; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_ADD_MEMBERSHIP), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_JOIN_GROUP)> join_group; #endif /// Socket option to leave a multicast group on a specified interface. @@ -73,7 +76,10 @@ typedef boost::asio::ip::detail::socket_option::multicast_request< typedef implementation_defined leave_group; #else typedef boost::asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_DROP_MEMBERSHIP, IPPROTO_IPV6, IPV6_LEAVE_GROUP> leave_group; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_DROP_MEMBERSHIP), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_LEAVE_GROUP)> leave_group; #endif /// Socket option for local interface to use for outgoing multicast packets. @@ -98,8 +104,10 @@ typedef boost::asio::ip::detail::socket_option::multicast_request< typedef implementation_defined outbound_interface; #else typedef boost::asio::ip::detail::socket_option::network_interface< - IPPROTO_IP, IP_MULTICAST_IF, IPPROTO_IPV6, IPV6_MULTICAST_IF> - outbound_interface; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_MULTICAST_IF), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_MULTICAST_IF)> outbound_interface; #endif /// Socket option for time-to-live associated with outgoing multicast packets. @@ -132,7 +140,10 @@ typedef boost::asio::ip::detail::socket_option::network_interface< typedef implementation_defined hops; #else typedef boost::asio::ip::detail::socket_option::multicast_hops< - IPPROTO_IP, IP_MULTICAST_TTL, IPPROTO_IPV6, IPV6_MULTICAST_HOPS> hops; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_MULTICAST_TTL), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_MULTICAST_HOPS)> hops; #endif /// Socket option determining whether outgoing multicast packets will be @@ -166,8 +177,10 @@ typedef boost::asio::ip::detail::socket_option::multicast_hops< typedef implementation_defined enable_loopback; #else typedef boost::asio::ip::detail::socket_option::multicast_enable_loopback< - IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> - enable_loopback; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_MULTICAST_LOOP), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_MULTICAST_LOOP)> enable_loopback; #endif } // namespace multicast diff --git a/include/boost/asio/ip/resolver_query_base.hpp b/include/boost/asio/ip/resolver_query_base.hpp index d61253ad..2ed5c0dd 100644 --- a/include/boost/asio/ip/resolver_query_base.hpp +++ b/include/boost/asio/ip/resolver_query_base.hpp @@ -63,31 +63,13 @@ public: #else enum flags { - canonical_name = AI_CANONNAME, - passive = AI_PASSIVE, - numeric_host = AI_NUMERICHOST, -# if defined(AI_NUMERICSERV) - numeric_service = AI_NUMERICSERV, -# else - numeric_service = 0, -# endif - // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but - // does not implement them. Therefore they are specifically excluded here. -# if defined(AI_V4MAPPED) && !defined(__QNXNTO__) - v4_mapped = AI_V4MAPPED, -# else - v4_mapped = 0, -# endif -# if defined(AI_ALL) && !defined(__QNXNTO__) - all_matching = AI_ALL, -# else - all_matching = 0, -# endif -# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__) - address_configured = AI_ADDRCONFIG -# else - address_configured = 0 -# endif + canonical_name = BOOST_ASIO_OS_DEF(AI_CANONNAME), + passive = BOOST_ASIO_OS_DEF(AI_PASSIVE), + numeric_host = BOOST_ASIO_OS_DEF(AI_NUMERICHOST), + numeric_service = BOOST_ASIO_OS_DEF(AI_NUMERICSERV), + v4_mapped = BOOST_ASIO_OS_DEF(AI_V4MAPPED), + all_matching = BOOST_ASIO_OS_DEF(AI_ALL), + address_configured = BOOST_ASIO_OS_DEF(AI_ADDRCONFIG) }; // Implement bitmask operations as shown in C++ Std [lib.bitmask.types]. diff --git a/include/boost/asio/ip/resolver_service.hpp b/include/boost/asio/ip/resolver_service.hpp index b5e889b7..6604a0e7 100644 --- a/include/boost/asio/ip/resolver_service.hpp +++ b/include/boost/asio/ip/resolver_service.hpp @@ -18,11 +18,16 @@ #include #include #include -#include #include #include #include +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#else +# include +#endif + #include namespace boost { @@ -59,8 +64,13 @@ public: private: // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef boost::asio::detail::winrt_resolver_service + service_impl_type; +#else typedef boost::asio::detail::resolver_service service_impl_type; +#endif public: /// The type of a resolver implementation. diff --git a/include/boost/asio/ip/tcp.hpp b/include/boost/asio/ip/tcp.hpp index 74ce406f..d2c865d4 100644 --- a/include/boost/asio/ip/tcp.hpp +++ b/include/boost/asio/ip/tcp.hpp @@ -52,25 +52,25 @@ public: /// Construct to represent the IPv4 TCP protocol. static tcp v4() { - return tcp(PF_INET); + return tcp(BOOST_ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 TCP protocol. static tcp v6() { - return tcp(PF_INET6); + return tcp(BOOST_ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_STREAM; + return BOOST_ASIO_OS_DEF(SOCK_STREAM); } /// Obtain an identifier for the protocol. int protocol() const { - return IPPROTO_TCP; + return BOOST_ASIO_OS_DEF(IPPROTO_TCP); } /// Obtain an identifier for the protocol family. @@ -123,7 +123,7 @@ public: typedef implementation_defined no_delay; #else typedef boost::asio::detail::socket_option::boolean< - IPPROTO_TCP, TCP_NODELAY> no_delay; + BOOST_ASIO_OS_DEF(IPPROTO_TCP), BOOST_ASIO_OS_DEF(TCP_NODELAY)> no_delay; #endif /// Compare two protocols for equality. diff --git a/include/boost/asio/ip/udp.hpp b/include/boost/asio/ip/udp.hpp index 2836b3c6..fefcc762 100644 --- a/include/boost/asio/ip/udp.hpp +++ b/include/boost/asio/ip/udp.hpp @@ -49,25 +49,25 @@ public: /// Construct to represent the IPv4 UDP protocol. static udp v4() { - return udp(PF_INET); + return udp(BOOST_ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 UDP protocol. static udp v6() { - return udp(PF_INET6); + return udp(BOOST_ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. int type() const { - return SOCK_DGRAM; + return BOOST_ASIO_OS_DEF(SOCK_DGRAM); } /// Obtain an identifier for the protocol. int protocol() const { - return IPPROTO_UDP; + return BOOST_ASIO_OS_DEF(IPPROTO_UDP); } /// Obtain an identifier for the protocol family. diff --git a/include/boost/asio/ip/unicast.hpp b/include/boost/asio/ip/unicast.hpp index 8fc9858c..616b9ffd 100644 --- a/include/boost/asio/ip/unicast.hpp +++ b/include/boost/asio/ip/unicast.hpp @@ -56,7 +56,10 @@ namespace unicast { typedef implementation_defined hops; #else typedef boost::asio::ip::detail::socket_option::unicast_hops< - IPPROTO_IP, IP_TTL, IPPROTO_IPV6, IPV6_UNICAST_HOPS> hops; + BOOST_ASIO_OS_DEF(IPPROTO_IP), + BOOST_ASIO_OS_DEF(IP_TTL), + BOOST_ASIO_OS_DEF(IPPROTO_IPV6), + BOOST_ASIO_OS_DEF(IPV6_UNICAST_HOPS)> hops; #endif } // namespace unicast diff --git a/include/boost/asio/raw_socket_service.hpp b/include/boost/asio/raw_socket_service.hpp index 5b0049b3..2c00fab3 100644 --- a/include/boost/asio/raw_socket_service.hpp +++ b/include/boost/asio/raw_socket_service.hpp @@ -22,7 +22,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #else # include @@ -56,7 +58,9 @@ public: private: // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::null_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) typedef detail::win_iocp_socket_service service_impl_type; #else typedef detail::reactive_socket_service service_impl_type; @@ -138,7 +142,7 @@ public: boost::system::error_code open(implementation_type& impl, const protocol_type& protocol, boost::system::error_code& ec) { - if (protocol.type() == SOCK_RAW) + if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_RAW)) service_impl_.open(impl, protocol, ec); else ec = boost::asio::error::invalid_argument; diff --git a/include/boost/asio/seq_packet_socket_service.hpp b/include/boost/asio/seq_packet_socket_service.hpp index 80ecea79..444c2b77 100644 --- a/include/boost/asio/seq_packet_socket_service.hpp +++ b/include/boost/asio/seq_packet_socket_service.hpp @@ -22,7 +22,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #else # include @@ -57,7 +59,9 @@ public: private: // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::null_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) typedef detail::win_iocp_socket_service service_impl_type; #else typedef detail::reactive_socket_service service_impl_type; @@ -140,7 +144,7 @@ public: boost::system::error_code open(implementation_type& impl, const protocol_type& protocol, boost::system::error_code& ec) { - if (protocol.type() == SOCK_SEQPACKET) + if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_SEQPACKET)) service_impl_.open(impl, protocol, ec); else ec = boost::asio::error::invalid_argument; @@ -314,13 +318,20 @@ public: /// Start an asynchronous send. template - void async_send(implementation_type& impl, + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(implementation_type& impl, const ConstBufferSequence& buffers, socket_base::message_flags flags, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { - service_impl_.async_send(impl, buffers, flags, + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + service_impl_.async_send(impl, buffers, flags, init.handler); + + return init.result.get(); } /// Receive some data from the peer. @@ -335,13 +346,21 @@ public: /// Start an asynchronous receive. template - void async_receive(implementation_type& impl, + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(implementation_type& impl, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, socket_base::message_flags& out_flags, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { - service_impl_.async_receive_with_flags(impl, buffers, in_flags, - out_flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + service_impl_.async_receive_with_flags(impl, + buffers, in_flags, out_flags, init.handler); + + return init.result.get(); } private: diff --git a/include/boost/asio/socket_acceptor_service.hpp b/include/boost/asio/socket_acceptor_service.hpp index 553fdd3b..1461809f 100644 --- a/include/boost/asio/socket_acceptor_service.hpp +++ b/include/boost/asio/socket_acceptor_service.hpp @@ -21,7 +21,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #else # include @@ -55,7 +57,9 @@ public: private: // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::null_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) typedef detail::win_iocp_socket_service service_impl_type; #else typedef detail::reactive_socket_service service_impl_type; diff --git a/include/boost/asio/socket_base.hpp b/include/boost/asio/socket_base.hpp index 9d16a45e..b504dd68 100644 --- a/include/boost/asio/socket_base.hpp +++ b/include/boost/asio/socket_base.hpp @@ -44,9 +44,9 @@ public: /// Shutdown both send and receive on the socket. shutdown_both = implementation_defined #else - shutdown_receive = boost::asio::detail::shutdown_receive, - shutdown_send = boost::asio::detail::shutdown_send, - shutdown_both = boost::asio::detail::shutdown_both + shutdown_receive = BOOST_ASIO_OS_DEF(SHUT_RD), + shutdown_send = BOOST_ASIO_OS_DEF(SHUT_WR), + shutdown_both = BOOST_ASIO_OS_DEF(SHUT_RDWR) #endif }; @@ -67,13 +67,13 @@ public: static const int message_end_of_record = implementation_defined; #else BOOST_ASIO_STATIC_CONSTANT(int, - message_peek = boost::asio::detail::message_peek); + message_peek = BOOST_ASIO_OS_DEF(MSG_PEEK)); BOOST_ASIO_STATIC_CONSTANT(int, - message_out_of_band = boost::asio::detail::message_out_of_band); + message_out_of_band = BOOST_ASIO_OS_DEF(MSG_OOB)); BOOST_ASIO_STATIC_CONSTANT(int, - message_do_not_route = boost::asio::detail::message_do_not_route); + message_do_not_route = BOOST_ASIO_OS_DEF(MSG_DONTROUTE)); BOOST_ASIO_STATIC_CONSTANT(int, - message_end_of_record = boost::asio::detail::message_end_of_record); + message_end_of_record = BOOST_ASIO_OS_DEF(MSG_EOR)); #endif /// Socket option to permit sending of broadcast messages. @@ -106,7 +106,8 @@ public: typedef implementation_defined broadcast; #else typedef boost::asio::detail::socket_option::boolean< - SOL_SOCKET, SO_BROADCAST> broadcast; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_BROADCAST)> + broadcast; #endif /// Socket option to enable socket-level debugging. @@ -139,7 +140,7 @@ public: typedef implementation_defined debug; #else typedef boost::asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DEBUG> debug; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_DEBUG)> debug; #endif /// Socket option to prevent routing, use local interfaces only. @@ -172,7 +173,8 @@ public: typedef implementation_defined do_not_route; #else typedef boost::asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DONTROUTE> do_not_route; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_DONTROUTE)> + do_not_route; #endif /// Socket option to send keep-alives. @@ -205,7 +207,7 @@ public: typedef implementation_defined keep_alive; #else typedef boost::asio::detail::socket_option::boolean< - SOL_SOCKET, SO_KEEPALIVE> keep_alive; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_KEEPALIVE)> keep_alive; #endif /// Socket option for the send buffer size of a socket. @@ -238,7 +240,8 @@ public: typedef implementation_defined send_buffer_size; #else typedef boost::asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDBUF> send_buffer_size; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_SNDBUF)> + send_buffer_size; #endif /// Socket option for the send low watermark. @@ -271,7 +274,8 @@ public: typedef implementation_defined send_low_watermark; #else typedef boost::asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDLOWAT> send_low_watermark; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_SNDLOWAT)> + send_low_watermark; #endif /// Socket option for the receive buffer size of a socket. @@ -304,7 +308,8 @@ public: typedef implementation_defined receive_buffer_size; #else typedef boost::asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVBUF> receive_buffer_size; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_RCVBUF)> + receive_buffer_size; #endif /// Socket option for the receive low watermark. @@ -337,7 +342,8 @@ public: typedef implementation_defined receive_low_watermark; #else typedef boost::asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVLOWAT> receive_low_watermark; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_RCVLOWAT)> + receive_low_watermark; #endif /// Socket option to allow the socket to be bound to an address that is @@ -371,7 +377,8 @@ public: typedef implementation_defined reuse_address; #else typedef boost::asio::detail::socket_option::boolean< - SOL_SOCKET, SO_REUSEADDR> reuse_address; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_REUSEADDR)> + reuse_address; #endif /// Socket option to specify whether the socket lingers on close if unsent @@ -406,7 +413,8 @@ public: typedef implementation_defined linger; #else typedef boost::asio::detail::socket_option::linger< - SOL_SOCKET, SO_LINGER> linger; + BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_LINGER)> + linger; #endif /// Socket option to report aborted connections on accept. @@ -495,7 +503,8 @@ public: #if defined(GENERATING_DOCUMENTATION) static const int max_connections = implementation_defined; #else - BOOST_ASIO_STATIC_CONSTANT(int, max_connections = SOMAXCONN); + BOOST_ASIO_STATIC_CONSTANT(int, max_connections + = BOOST_ASIO_OS_DEF(SOMAXCONN)); #endif protected: diff --git a/include/boost/asio/ssl/detail/io.hpp b/include/boost/asio/ssl/detail/io.hpp index b64c49a1..7acf9e55 100644 --- a/include/boost/asio/ssl/detail/io.hpp +++ b/include/boost/asio/ssl/detail/io.hpp @@ -97,6 +97,7 @@ public: core_(core), op_(op), start_(0), + want_(engine::want_nothing), bytes_transferred_(0), handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) { diff --git a/include/boost/asio/stream_socket_service.hpp b/include/boost/asio/stream_socket_service.hpp index 91456299..a6624c2e 100644 --- a/include/boost/asio/stream_socket_service.hpp +++ b/include/boost/asio/stream_socket_service.hpp @@ -22,7 +22,9 @@ #include #include -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) # include #else # include @@ -56,7 +58,9 @@ public: private: // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::winrt_ssocket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) typedef detail::win_iocp_socket_service service_impl_type; #else typedef detail::reactive_socket_service service_impl_type; @@ -138,7 +142,7 @@ public: boost::system::error_code open(implementation_type& impl, const protocol_type& protocol, boost::system::error_code& ec) { - if (protocol.type() == SOCK_STREAM) + if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_STREAM)) service_impl_.open(impl, protocol, ec); else ec = boost::asio::error::invalid_argument; diff --git a/include/boost/asio/use_future.hpp b/include/boost/asio/use_future.hpp index 5bf71770..d1ebefed 100644 --- a/include/boost/asio/use_future.hpp +++ b/include/boost/asio/use_future.hpp @@ -47,7 +47,7 @@ public: typedef Allocator allocator_type; /// Construct using default-constructed allocator. - constexpr use_future_t() + BOOST_ASIO_CONSTEXPR use_future_t() { } @@ -78,7 +78,11 @@ private: /** * See the documentation for boost::asio::use_future_t for a usage example. */ +#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr use_future_t<> use_future; +#elif defined(BOOST_ASIO_MSVC) +__declspec(selectany) use_future_t<> use_future; +#endif } // namespace asio } // namespace boost diff --git a/include/boost/asio/windows/random_access_handle_service.hpp b/include/boost/asio/windows/random_access_handle_service.hpp index 8d33fc6a..9bf99c5f 100644 --- a/include/boost/asio/windows/random_access_handle_service.hpp +++ b/include/boost/asio/windows/random_access_handle_service.hpp @@ -21,7 +21,6 @@ || defined(GENERATING_DOCUMENTATION) #include -#include #include #include #include diff --git a/include/boost/asio/write_at.hpp b/include/boost/asio/write_at.hpp index 2edd05a2..6c84335c 100644 --- a/include/boost/asio/write_at.hpp +++ b/include/boost/asio/write_at.hpp @@ -407,7 +407,12 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, * @li An error occurred. * * This operation is implemented in terms of zero or more calls to the device's - * async_write_some_at function. + * async_write_some_at function, and is known as a composed operation. + * The program must ensure that the device performs no overlapping + * write operations (such as async_write_at, the device's async_write_some_at + * function, or any other composed operations that perform writes) until this + * operation completes. Operations are overlapping if the regions defined by + * their offsets, and the numbers of bytes to write, intersect. * * @param d The device to which the data is to be written. The type must support * the AsyncRandomAccessWriteDevice concept. @@ -466,7 +471,12 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * @li The completion_condition function object returns 0. * * This operation is implemented in terms of zero or more calls to the device's - * async_write_some_at function. + * async_write_some_at function, and is known as a composed operation. + * The program must ensure that the device performs no overlapping + * write operations (such as async_write_at, the device's async_write_some_at + * function, or any other composed operations that perform writes) until this + * operation completes. Operations are overlapping if the regions defined by + * their offsets, and the numbers of bytes to write, intersect. * * @param d The device to which the data is to be written. The type must support * the AsyncRandomAccessWriteDevice concept. @@ -542,7 +552,12 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * @li An error occurred. * * This operation is implemented in terms of zero or more calls to the device's - * async_write_some_at function. + * async_write_some_at function, and is known as a composed operation. + * The program must ensure that the device performs no overlapping + * write operations (such as async_write_at, the device's async_write_some_at + * function, or any other composed operations that perform writes) until this + * operation completes. Operations are overlapping if the regions defined by + * their offsets, and the numbers of bytes to write, intersect. * * @param d The device to which the data is to be written. The type must support * the AsyncRandomAccessWriteDevice concept. @@ -589,7 +604,12 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * @li The completion_condition function object returns 0. * * This operation is implemented in terms of zero or more calls to the device's - * async_write_some_at function. + * async_write_some_at function, and is known as a composed operation. + * The program must ensure that the device performs no overlapping + * write operations (such as async_write_at, the device's async_write_some_at + * function, or any other composed operations that perform writes) until this + * operation completes. Operations are overlapping if the regions defined by + * their offsets, and the numbers of bytes to write, intersect. * * @param d The device to which the data is to be written. The type must support * the AsyncRandomAccessWriteDevice concept. diff --git a/test/Jamfile b/test/Jamfile index 6b10b5dd..a2c9e620 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -25,8 +25,7 @@ if $(UNIX) } template asio_unit_test - : @boost/libs/thread/build/boost_thread - @boost/libs/regex/build/boost_regex + : @boost/libs/regex/build/boost_regex @boost/libs/test/build/boost_test_exec_monitor @boost_system/libs/system/build/boost_system : ../../.. @boost @boost_system diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 76128297..aaeced02 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,7 +38,6 @@ project : requirements /boost/date_time//boost_date_time /boost/system//boost_system - /boost/thread//boost_thread /boost/regex//boost_regex /boost/test//boost_test_exec_monitor BOOST_ALL_NO_LIB=1 diff --git a/test/buffered_read_stream.cpp b/test/buffered_read_stream.cpp index 430e9dc3..48f3ce10 100644 --- a/test/buffered_read_stream.cpp +++ b/test/buffered_read_stream.cpp @@ -17,12 +17,19 @@ #include #include +#include "archetypes/async_result.hpp" #include #include #include #include #include "unit_test.hpp" +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + #if defined(BOOST_ASIO_HAS_BOOST_BIND) # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) @@ -32,6 +39,107 @@ typedef boost::asio::buffered_read_stream< boost::asio::ip::tcp::socket> stream_type; +void write_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void fill_handler(const boost::system::error_code&, std::size_t) +{ +} + +void read_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void test_compile() +{ +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using boost::array; +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using std::array; +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + + using namespace boost::asio; + + try + { + io_service ios; + char mutable_char_buffer[128] = ""; + const char const_char_buffer[128] = ""; + array mutable_buffers = {{ + boost::asio::buffer(mutable_char_buffer, 10), + boost::asio::buffer(mutable_char_buffer + 10, 10) }}; + array const_buffers = {{ + boost::asio::buffer(const_char_buffer, 10), + boost::asio::buffer(const_char_buffer + 10, 10) }}; + archetypes::lazy_handler lazy; + boost::system::error_code ec; + + stream_type stream1(ios); + stream_type stream2(ios, 1024); + + io_service& ios_ref = stream1.get_io_service(); + (void)ios_ref; + + stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer(); + (void)lowest_layer; + + stream1.write_some(buffer(mutable_char_buffer)); + stream1.write_some(buffer(const_char_buffer)); + stream1.write_some(mutable_buffers); + stream1.write_some(const_buffers); + stream1.write_some(null_buffers()); + stream1.write_some(buffer(mutable_char_buffer), ec); + stream1.write_some(buffer(const_char_buffer), ec); + stream1.write_some(mutable_buffers, ec); + stream1.write_some(const_buffers, ec); + stream1.write_some(null_buffers(), ec); + + stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler); + stream1.async_write_some(buffer(const_char_buffer), &write_some_handler); + stream1.async_write_some(mutable_buffers, &write_some_handler); + stream1.async_write_some(const_buffers, &write_some_handler); + stream1.async_write_some(null_buffers(), &write_some_handler); + int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy); + (void)i1; + int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy); + (void)i2; + int i3 = stream1.async_write_some(mutable_buffers, lazy); + (void)i3; + int i4 = stream1.async_write_some(const_buffers, lazy); + (void)i4; + int i5 = stream1.async_write_some(null_buffers(), lazy); + (void)i5; + + stream1.fill(); + stream1.fill(ec); + + stream1.async_fill(&fill_handler); + int i6 = stream1.async_fill(lazy); + (void)i6; + + stream1.read_some(buffer(mutable_char_buffer)); + stream1.read_some(mutable_buffers); + stream1.read_some(null_buffers()); + stream1.read_some(buffer(mutable_char_buffer), ec); + stream1.read_some(mutable_buffers, ec); + stream1.read_some(null_buffers(), ec); + + stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler); + stream1.async_read_some(mutable_buffers, &read_some_handler); + stream1.async_read_some(null_buffers(), &read_some_handler); + int i7 = stream1.async_read_some(buffer(mutable_char_buffer), lazy); + (void)i7; + int i8 = stream1.async_read_some(mutable_buffers, lazy); + (void)i8; + int i9 = stream1.async_read_some(null_buffers(), lazy); + (void)i9; + } + catch (std::exception&) + { + } +} + void test_sync_operations() { using namespace std; // For memcmp. @@ -224,6 +332,7 @@ void test_async_operations() BOOST_ASIO_TEST_SUITE ( "buffered_read_stream", + BOOST_ASIO_TEST_CASE(test_compile) BOOST_ASIO_TEST_CASE(test_sync_operations) BOOST_ASIO_TEST_CASE(test_async_operations) ) diff --git a/test/buffered_stream.cpp b/test/buffered_stream.cpp index 1a5531f0..41998d49 100644 --- a/test/buffered_stream.cpp +++ b/test/buffered_stream.cpp @@ -17,12 +17,19 @@ #include #include +#include "archetypes/async_result.hpp" #include #include #include #include #include "unit_test.hpp" +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + #if defined(BOOST_ASIO_HAS_BOOST_BIND) # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) @@ -32,6 +39,118 @@ typedef boost::asio::buffered_stream< boost::asio::ip::tcp::socket> stream_type; +void write_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void flush_handler(const boost::system::error_code&, std::size_t) +{ +} + +void fill_handler(const boost::system::error_code&, std::size_t) +{ +} + +void read_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void test_compile() +{ +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using boost::array; +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using std::array; +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + + using namespace boost::asio; + + try + { + io_service ios; + char mutable_char_buffer[128] = ""; + const char const_char_buffer[128] = ""; + array mutable_buffers = {{ + boost::asio::buffer(mutable_char_buffer, 10), + boost::asio::buffer(mutable_char_buffer + 10, 10) }}; + array const_buffers = {{ + boost::asio::buffer(const_char_buffer, 10), + boost::asio::buffer(const_char_buffer + 10, 10) }}; + archetypes::lazy_handler lazy; + boost::system::error_code ec; + + stream_type stream1(ios); + stream_type stream2(ios, 1024, 1024); + + io_service& ios_ref = stream1.get_io_service(); + (void)ios_ref; + + stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer(); + (void)lowest_layer; + + stream1.write_some(buffer(mutable_char_buffer)); + stream1.write_some(buffer(const_char_buffer)); + stream1.write_some(mutable_buffers); + stream1.write_some(const_buffers); + stream1.write_some(null_buffers()); + stream1.write_some(buffer(mutable_char_buffer), ec); + stream1.write_some(buffer(const_char_buffer), ec); + stream1.write_some(mutable_buffers, ec); + stream1.write_some(const_buffers, ec); + stream1.write_some(null_buffers(), ec); + + stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler); + stream1.async_write_some(buffer(const_char_buffer), &write_some_handler); + stream1.async_write_some(mutable_buffers, &write_some_handler); + stream1.async_write_some(const_buffers, &write_some_handler); + stream1.async_write_some(null_buffers(), &write_some_handler); + int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy); + (void)i1; + int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy); + (void)i2; + int i3 = stream1.async_write_some(mutable_buffers, lazy); + (void)i3; + int i4 = stream1.async_write_some(const_buffers, lazy); + (void)i4; + int i5 = stream1.async_write_some(null_buffers(), lazy); + (void)i5; + + stream1.flush(); + stream1.flush(ec); + + stream1.async_flush(&flush_handler); + int i6 = stream1.async_flush(lazy); + (void)i6; + + stream1.fill(); + stream1.fill(ec); + + stream1.async_fill(&fill_handler); + int i7 = stream1.async_fill(lazy); + (void)i7; + + stream1.read_some(buffer(mutable_char_buffer)); + stream1.read_some(mutable_buffers); + stream1.read_some(null_buffers()); + stream1.read_some(buffer(mutable_char_buffer), ec); + stream1.read_some(mutable_buffers, ec); + stream1.read_some(null_buffers(), ec); + + stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler); + stream1.async_read_some(mutable_buffers, &read_some_handler); + stream1.async_read_some(null_buffers(), &read_some_handler); + int i8 = stream1.async_read_some(buffer(mutable_char_buffer), lazy); + (void)i8; + int i9 = stream1.async_read_some(mutable_buffers, lazy); + (void)i9; + int i10 = stream1.async_read_some(null_buffers(), lazy); + (void)i10; + } + catch (std::exception&) + { + } +} + void test_sync_operations() { using namespace std; // For memcmp. @@ -239,6 +358,7 @@ void test_async_operations() BOOST_ASIO_TEST_SUITE ( "buffered_stream", + BOOST_ASIO_TEST_CASE(test_compile) BOOST_ASIO_TEST_CASE(test_sync_operations) BOOST_ASIO_TEST_CASE(test_async_operations) ) diff --git a/test/buffered_write_stream.cpp b/test/buffered_write_stream.cpp index 6b983d06..bdd050df 100644 --- a/test/buffered_write_stream.cpp +++ b/test/buffered_write_stream.cpp @@ -17,12 +17,19 @@ #include #include +#include "archetypes/async_result.hpp" #include #include #include #include #include "unit_test.hpp" +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# include +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + #if defined(BOOST_ASIO_HAS_BOOST_BIND) # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) @@ -32,6 +39,107 @@ typedef boost::asio::buffered_write_stream< boost::asio::ip::tcp::socket> stream_type; +void write_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void flush_handler(const boost::system::error_code&, std::size_t) +{ +} + +void read_some_handler(const boost::system::error_code&, std::size_t) +{ +} + +void test_compile() +{ +#if defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using boost::array; +#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + using std::array; +#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY) + + using namespace boost::asio; + + try + { + io_service ios; + char mutable_char_buffer[128] = ""; + const char const_char_buffer[128] = ""; + array mutable_buffers = {{ + boost::asio::buffer(mutable_char_buffer, 10), + boost::asio::buffer(mutable_char_buffer + 10, 10) }}; + array const_buffers = {{ + boost::asio::buffer(const_char_buffer, 10), + boost::asio::buffer(const_char_buffer + 10, 10) }}; + archetypes::lazy_handler lazy; + boost::system::error_code ec; + + stream_type stream1(ios); + stream_type stream2(ios, 1024); + + io_service& ios_ref = stream1.get_io_service(); + (void)ios_ref; + + stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer(); + (void)lowest_layer; + + stream1.write_some(buffer(mutable_char_buffer)); + stream1.write_some(buffer(const_char_buffer)); + stream1.write_some(mutable_buffers); + stream1.write_some(const_buffers); + stream1.write_some(null_buffers()); + stream1.write_some(buffer(mutable_char_buffer), ec); + stream1.write_some(buffer(const_char_buffer), ec); + stream1.write_some(mutable_buffers, ec); + stream1.write_some(const_buffers, ec); + stream1.write_some(null_buffers(), ec); + + stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler); + stream1.async_write_some(buffer(const_char_buffer), &write_some_handler); + stream1.async_write_some(mutable_buffers, &write_some_handler); + stream1.async_write_some(const_buffers, &write_some_handler); + stream1.async_write_some(null_buffers(), &write_some_handler); + int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy); + (void)i1; + int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy); + (void)i2; + int i3 = stream1.async_write_some(mutable_buffers, lazy); + (void)i3; + int i4 = stream1.async_write_some(const_buffers, lazy); + (void)i4; + int i5 = stream1.async_write_some(null_buffers(), lazy); + (void)i5; + + stream1.flush(); + stream1.flush(ec); + + stream1.async_flush(&flush_handler); + int i6 = stream1.async_flush(lazy); + (void)i6; + + stream1.read_some(buffer(mutable_char_buffer)); + stream1.read_some(mutable_buffers); + stream1.read_some(null_buffers()); + stream1.read_some(buffer(mutable_char_buffer), ec); + stream1.read_some(mutable_buffers, ec); + stream1.read_some(null_buffers(), ec); + + stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler); + stream1.async_read_some(mutable_buffers, &read_some_handler); + stream1.async_read_some(null_buffers(), &read_some_handler); + int i7 = stream1.async_read_some(buffer(mutable_char_buffer), lazy); + (void)i7; + int i8 = stream1.async_read_some(mutable_buffers, lazy); + (void)i8; + int i9 = stream1.async_read_some(null_buffers(), lazy); + (void)i9; + } + catch (std::exception&) + { + } +} + void test_sync_operations() { using namespace std; // For memcmp. @@ -239,6 +347,7 @@ void test_async_operations() BOOST_ASIO_TEST_SUITE ( "buffered_write_stream", + BOOST_ASIO_TEST_CASE(test_compile) BOOST_ASIO_TEST_CASE(test_sync_operations) BOOST_ASIO_TEST_CASE(test_async_operations) ) diff --git a/test/deadline_timer.cpp b/test/deadline_timer.cpp index 7929ffc2..16998126 100644 --- a/test/deadline_timer.cpp +++ b/test/deadline_timer.cpp @@ -20,11 +20,11 @@ #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) -#include #include #include "archetypes/async_result.hpp" #include #include +#include using namespace boost::posix_time; @@ -309,7 +309,7 @@ void deadline_timer_thread_test() boost::asio::deadline_timer t2(ios); int count = 0; - boost::thread th(boost::bind(io_service_run, &ios)); + boost::asio::detail::thread th(boost::bind(io_service_run, &ios)); t2.expires_from_now(boost::posix_time::seconds(2)); t2.wait(); diff --git a/test/generic/datagram_protocol.cpp b/test/generic/datagram_protocol.cpp index 86e2ffb4..b7fe8207 100644 --- a/test/generic/datagram_protocol.cpp +++ b/test/generic/datagram_protocol.cpp @@ -21,6 +21,10 @@ #include #include "../unit_test.hpp" +#if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# define generic cpp_generic +#endif + //------------------------------------------------------------------------------ // generic_datagram_protocol_socket_compile test @@ -49,6 +53,10 @@ void test() namespace generic = boost::asio::generic; typedef generic::datagram_protocol dp; + const int af_inet = BOOST_ASIO_OS_DEF(AF_INET); + const int ipproto_udp = BOOST_ASIO_OS_DEF(IPPROTO_UDP); + const int sock_dgram = BOOST_ASIO_OS_DEF(SOCK_DGRAM); + try { io_service ios; @@ -62,14 +70,17 @@ void test() // basic_datagram_socket constructors. dp::socket socket1(ios); - dp::socket socket2(ios, dp(AF_INET, IPPROTO_UDP)); + dp::socket socket2(ios, dp(af_inet, ipproto_udp)); dp::socket socket3(ios, dp::endpoint()); - int native_socket1 = ::socket(AF_INET, SOCK_DGRAM, 0); - dp::socket socket4(ios, dp(AF_INET, IPPROTO_UDP), native_socket1); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket1 = ::socket(af_inet, sock_dgram, 0); + dp::socket socket4(ios, dp(af_inet, ipproto_udp), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) dp::socket socket5(std::move(socket4)); - dp::socket socket6(boost::asio::ip::udp::socket(ios)); + boost::asio::ip::udp::socket udp_socket(ios); + dp::socket socket6(std::move(udp_socket)); #endif // defined(BOOST_ASIO_HAS_MOVE) // basic_datagram_socket operators. @@ -90,13 +101,15 @@ void test() dp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer(); (void)lowest_layer; - socket1.open(dp(AF_INET, IPPROTO_UDP)); - socket1.open(dp(AF_INET, IPPROTO_UDP), ec); + socket1.open(dp(af_inet, ipproto_udp)); + socket1.open(dp(af_inet, ipproto_udp), ec); - int native_socket2 = ::socket(AF_INET, SOCK_DGRAM, 0); - socket1.assign(dp(AF_INET, IPPROTO_UDP), native_socket2); - int native_socket3 = ::socket(AF_INET, SOCK_DGRAM, 0); - socket1.assign(dp(AF_INET, IPPROTO_UDP), native_socket3, ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket2 = ::socket(af_inet, sock_dgram, 0); + socket1.assign(dp(af_inet, ipproto_udp), native_socket2); + int native_socket3 = ::socket(af_inet, sock_dgram, 0); + socket1.assign(dp(af_inet, ipproto_udp), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/generic/raw_protocol.cpp b/test/generic/raw_protocol.cpp index 4c844ed4..d695d7b2 100644 --- a/test/generic/raw_protocol.cpp +++ b/test/generic/raw_protocol.cpp @@ -21,6 +21,10 @@ #include #include "../unit_test.hpp" +#if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# define generic cpp_generic +#endif + //------------------------------------------------------------------------------ // generic_raw_protocol_socket_compile test @@ -49,6 +53,10 @@ void test() namespace generic = boost::asio::generic; typedef generic::raw_protocol rp; + const int af_inet = BOOST_ASIO_OS_DEF(AF_INET); + const int ipproto_icmp = BOOST_ASIO_OS_DEF(IPPROTO_ICMP); + const int sock_raw = BOOST_ASIO_OS_DEF(SOCK_RAW); + try { io_service ios; @@ -62,14 +70,17 @@ void test() // basic_raw_socket constructors. rp::socket socket1(ios); - rp::socket socket2(ios, rp(AF_INET, IPPROTO_ICMP)); + rp::socket socket2(ios, rp(af_inet, ipproto_icmp)); rp::socket socket3(ios, rp::endpoint()); - int native_socket1 = ::socket(AF_INET, SOCK_DGRAM, 0); - rp::socket socket4(ios, rp(AF_INET, IPPROTO_ICMP), native_socket1); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket1 = ::socket(af_inet, sock_raw, 0); + rp::socket socket4(ios, rp(af_inet, ipproto_icmp), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) rp::socket socket5(std::move(socket4)); - rp::socket socket6(boost::asio::ip::icmp::socket(ios)); + boost::asio::ip::icmp::socket icmp_socket(ios); + rp::socket socket6(std::move(icmp_socket)); #endif // defined(BOOST_ASIO_HAS_MOVE) // basic_datagram_socket operators. @@ -90,13 +101,15 @@ void test() rp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer(); (void)lowest_layer; - socket1.open(rp(AF_INET, IPPROTO_ICMP)); - socket1.open(rp(AF_INET, IPPROTO_ICMP), ec); + socket1.open(rp(af_inet, ipproto_icmp)); + socket1.open(rp(af_inet, ipproto_icmp), ec); - int native_socket2 = ::socket(AF_INET, SOCK_DGRAM, 0); - socket1.assign(rp(AF_INET, IPPROTO_ICMP), native_socket2); - int native_socket3 = ::socket(AF_INET, SOCK_DGRAM, 0); - socket1.assign(rp(AF_INET, IPPROTO_ICMP), native_socket3, ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket2 = ::socket(af_inet, sock_raw, 0); + socket1.assign(rp(af_inet, ipproto_icmp), native_socket2); + int native_socket3 = ::socket(af_inet, sock_raw, 0); + socket1.assign(rp(af_inet, ipproto_icmp), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/generic/seq_packet_protocol.cpp b/test/generic/seq_packet_protocol.cpp index ed07f280..f582dccf 100644 --- a/test/generic/seq_packet_protocol.cpp +++ b/test/generic/seq_packet_protocol.cpp @@ -20,6 +20,10 @@ #include #include "../unit_test.hpp" +#if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# define generic cpp_generic +#endif + //------------------------------------------------------------------------------ // generic_seq_packet_protocol_socket_compile test @@ -48,6 +52,9 @@ void test() namespace generic = boost::asio::generic; typedef generic::seq_packet_protocol spp; + const int af_inet = BOOST_ASIO_OS_DEF(AF_INET); + const int sock_seqpacket = BOOST_ASIO_OS_DEF(SOCK_SEQPACKET); + try { io_service ios; @@ -62,10 +69,12 @@ void test() // basic_seq_packet_socket constructors. spp::socket socket1(ios); - spp::socket socket2(ios, spp(AF_INET, 0)); + spp::socket socket2(ios, spp(af_inet, 0)); spp::socket socket3(ios, spp::endpoint()); - int native_socket1 = ::socket(AF_INET, SOCK_SEQPACKET, 0); - spp::socket socket4(ios, spp(AF_INET, 0), native_socket1); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket1 = ::socket(af_inet, sock_seqpacket, 0); + spp::socket socket4(ios, spp(af_inet, 0), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) spp::socket socket5(std::move(socket4)); @@ -88,13 +97,15 @@ void test() spp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer(); (void)lowest_layer; - socket1.open(spp(AF_INET, 0)); - socket1.open(spp(AF_INET, 0), ec); + socket1.open(spp(af_inet, 0)); + socket1.open(spp(af_inet, 0), ec); - int native_socket2 = ::socket(AF_INET, SOCK_SEQPACKET, 0); - socket1.assign(spp(AF_INET, 0), native_socket2); - int native_socket3 = ::socket(AF_INET, SOCK_SEQPACKET, 0); - socket1.assign(spp(AF_INET, 0), native_socket3, ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket2 = ::socket(af_inet, sock_seqpacket, 0); + socket1.assign(spp(af_inet, 0), native_socket2); + int native_socket3 = ::socket(af_inet, sock_seqpacket, 0); + socket1.assign(spp(af_inet, 0), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/generic/stream_protocol.cpp b/test/generic/stream_protocol.cpp index b4ff7960..1e8801ed 100644 --- a/test/generic/stream_protocol.cpp +++ b/test/generic/stream_protocol.cpp @@ -21,6 +21,10 @@ #include #include "../unit_test.hpp" +#if defined(__cplusplus_cli) || defined(__cplusplus_winrt) +# define generic cpp_generic +#endif + //------------------------------------------------------------------------------ // generic_stream_protocol_socket_compile test @@ -57,6 +61,10 @@ void test() namespace generic = boost::asio::generic; typedef generic::stream_protocol sp; + const int af_inet = BOOST_ASIO_OS_DEF(AF_INET); + const int ipproto_tcp = BOOST_ASIO_OS_DEF(IPPROTO_TCP); + const int sock_stream = BOOST_ASIO_OS_DEF(SOCK_STREAM); + try { io_service ios; @@ -70,14 +78,19 @@ void test() // basic_stream_socket constructors. sp::socket socket1(ios); - sp::socket socket2(ios, sp(AF_INET, IPPROTO_TCP)); + sp::socket socket2(ios, sp(af_inet, ipproto_tcp)); sp::socket socket3(ios, sp::endpoint()); - int native_socket1 = ::socket(AF_INET, SOCK_STREAM, 0); - sp::socket socket4(ios, sp(AF_INET, IPPROTO_TCP), native_socket1); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + Windows::Networking::Sockets::StreamSocket^ native_socket1 = nullptr; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket1 = ::socket(af_inet, sock_stream, 0); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + sp::socket socket4(ios, sp(af_inet, ipproto_tcp), native_socket1); #if defined(BOOST_ASIO_HAS_MOVE) sp::socket socket5(std::move(socket4)); - sp::socket socket6(boost::asio::ip::tcp::socket(ios)); + boost::asio::ip::tcp::socket tcp_socket(ios); + sp::socket socket6(std::move(tcp_socket)); #endif // defined(BOOST_ASIO_HAS_MOVE) // basic_stream_socket operators. @@ -98,13 +111,21 @@ void test() sp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer(); (void)lowest_layer; - socket1.open(sp(AF_INET, IPPROTO_TCP)); - socket1.open(sp(AF_INET, IPPROTO_TCP), ec); + socket1.open(sp(af_inet, ipproto_tcp)); + socket1.open(sp(af_inet, ipproto_tcp), ec); - int native_socket2 = ::socket(AF_INET, SOCK_STREAM, 0); - socket1.assign(sp(AF_INET, IPPROTO_TCP), native_socket2); - int native_socket3 = ::socket(AF_INET, SOCK_STREAM, 0); - socket1.assign(sp(AF_INET, IPPROTO_TCP), native_socket3, ec); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + Windows::Networking::Sockets::StreamSocket^ native_socket2 = nullptr; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket2 = ::socket(af_inet, sock_stream, 0); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + socket1.assign(sp(af_inet, ipproto_tcp), native_socket2); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + Windows::Networking::Sockets::StreamSocket^ native_socket3 = nullptr; +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) + int native_socket3 = ::socket(af_inet, sock_stream, 0); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + socket1.assign(sp(af_inet, ipproto_tcp), native_socket3, ec); bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/io_service.cpp b/test/io_service.cpp index a3f68b7b..2aa59ad2 100644 --- a/test/io_service.cpp +++ b/test/io_service.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "unit_test.hpp" #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) @@ -26,7 +27,6 @@ #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) #if defined(BOOST_ASIO_HAS_BOOST_BIND) -# include # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) # include @@ -221,8 +221,8 @@ void io_service_test() BOOST_ASIO_CHECK(!ios.stopped()); ios.post(bindns::bind(start_sleep_increments, &ios, &count)); ios.post(bindns::bind(start_sleep_increments, &ios, &count2)); - boost::thread thread1(bindns::bind(io_service_run, &ios)); - boost::thread thread2(bindns::bind(io_service_run, &ios)); + boost::asio::detail::thread thread1(bindns::bind(io_service_run, &ios)); + boost::asio::detail::thread thread2(bindns::bind(io_service_run, &ios)); thread1.join(); thread2.join(); diff --git a/test/ip/icmp.cpp b/test/ip/icmp.cpp index c23a6630..5a45b72f 100644 --- a/test/ip/icmp.cpp +++ b/test/ip/icmp.cpp @@ -74,8 +74,10 @@ void test() ip::icmp::socket socket3(ios, ip::icmp::v6()); ip::icmp::socket socket4(ios, ip::icmp::endpoint(ip::icmp::v4(), 0)); ip::icmp::socket socket5(ios, ip::icmp::endpoint(ip::icmp::v6(), 0)); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket1 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ip::icmp::socket socket6(ios, ip::icmp::v4(), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) ip::icmp::socket socket7(std::move(socket6)); @@ -108,10 +110,12 @@ void test() socket1.open(ip::icmp::v4(), ec); socket1.open(ip::icmp::v6(), ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket2 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); socket1.assign(ip::icmp::v4(), native_socket2); int native_socket3 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); socket1.assign(ip::icmp::v4(), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/ip/tcp.cpp b/test/ip/tcp.cpp index 79732249..355747c7 100644 --- a/test/ip/tcp.cpp +++ b/test/ip/tcp.cpp @@ -197,11 +197,13 @@ void test() ip::tcp::socket socket3(ios, ip::tcp::v6()); ip::tcp::socket socket4(ios, ip::tcp::endpoint(ip::tcp::v4(), 0)); ip::tcp::socket socket5(ios, ip::tcp::endpoint(ip::tcp::v6(), 0)); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket1 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ip::tcp::socket socket6(ios, ip::tcp::v4(), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) - ip::tcp::socket socket7(std::move(socket6)); + ip::tcp::socket socket7(std::move(socket5)); #endif // defined(BOOST_ASIO_HAS_MOVE) // basic_stream_socket operators. @@ -231,10 +233,12 @@ void test() socket1.open(ip::tcp::v4(), ec); socket1.open(ip::tcp::v6(), ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket2 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); socket1.assign(ip::tcp::v4(), native_socket2); int native_socket3 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); socket1.assign(ip::tcp::v4(), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; @@ -652,11 +656,13 @@ void test() ip::tcp::acceptor acceptor3(ios, ip::tcp::v6()); ip::tcp::acceptor acceptor4(ios, ip::tcp::endpoint(ip::tcp::v4(), 0)); ip::tcp::acceptor acceptor5(ios, ip::tcp::endpoint(ip::tcp::v6(), 0)); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_acceptor1 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ip::tcp::acceptor acceptor6(ios, ip::tcp::v4(), native_acceptor1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) - ip::tcp::acceptor acceptor7(std::move(acceptor6)); + ip::tcp::acceptor acceptor7(std::move(acceptor5)); #endif // defined(BOOST_ASIO_HAS_MOVE) // basic_socket_acceptor operators. @@ -678,10 +684,12 @@ void test() acceptor1.open(ip::tcp::v4(), ec); acceptor1.open(ip::tcp::v6(), ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_acceptor2 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); acceptor1.assign(ip::tcp::v4(), native_acceptor2); int native_acceptor3 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); acceptor1.assign(ip::tcp::v4(), native_acceptor3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = acceptor1.is_open(); (void)is_open; diff --git a/test/ip/udp.cpp b/test/ip/udp.cpp index f0225ea0..ce73b5a2 100644 --- a/test/ip/udp.cpp +++ b/test/ip/udp.cpp @@ -79,8 +79,10 @@ void test() ip::udp::socket socket3(ios, ip::udp::v6()); ip::udp::socket socket4(ios, ip::udp::endpoint(ip::udp::v4(), 0)); ip::udp::socket socket5(ios, ip::udp::endpoint(ip::udp::v6(), 0)); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket1 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ip::udp::socket socket6(ios, ip::udp::v4(), native_socket1); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #if defined(BOOST_ASIO_HAS_MOVE) ip::udp::socket socket7(std::move(socket6)); @@ -113,10 +115,12 @@ void test() socket1.open(ip::udp::v4(), ec); socket1.open(ip::udp::v6(), ec); +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) int native_socket2 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); socket1.assign(ip::udp::v4(), native_socket2); int native_socket3 = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); socket1.assign(ip::udp::v4(), native_socket3, ec); +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) bool is_open = socket1.is_open(); (void)is_open; diff --git a/test/ssl/Jamfile b/test/ssl/Jamfile index ccb8b02b..716ff49c 100644 --- a/test/ssl/Jamfile +++ b/test/ssl/Jamfile @@ -24,8 +24,7 @@ if $(UNIX) } template unit_test - : @boost/libs/thread/build/boost_thread - @boost/libs/system/build/boost_system + : @boost/libs/system/build/boost_system : @boost/libs/test/build/boost_test_exec_monitor : ../../../.. BOOST_ALL_NO_LIB=1 diff --git a/test/ssl/Jamfile.v2 b/test/ssl/Jamfile.v2 index 706316d7..02ebbe59 100644 --- a/test/ssl/Jamfile.v2 +++ b/test/ssl/Jamfile.v2 @@ -35,7 +35,6 @@ local USE_SELECT = project : requirements /boost/date_time//boost_date_time - /boost/thread//boost_thread /boost/test//boost_test_exec_monitor BOOST_ALL_NO_LIB=1 multi diff --git a/test/strand.cpp b/test/strand.cpp index 8c81ba0f..01ba191a 100644 --- a/test/strand.cpp +++ b/test/strand.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "unit_test.hpp" #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) @@ -27,7 +28,6 @@ #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) #if defined(BOOST_ASIO_HAS_BOOST_BIND) -# include # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) # include @@ -144,8 +144,8 @@ void strand_test() count = 0; ios.reset(); ios.post(bindns::bind(start_sleep_increments, &ios, &s, &count)); - boost::thread thread1(bindns::bind(io_service_run, &ios)); - boost::thread thread2(bindns::bind(io_service_run, &ios)); + boost::asio::detail::thread thread1(bindns::bind(io_service_run, &ios)); + boost::asio::detail::thread thread2(bindns::bind(io_service_run, &ios)); // Check all events run one after another even though there are two threads. timer timer1(ios, chronons::seconds(3)); diff --git a/test/system_timer.cpp b/test/system_timer.cpp index 07facb63..e48ac244 100644 --- a/test/system_timer.cpp +++ b/test/system_timer.cpp @@ -26,9 +26,9 @@ #if defined(BOOST_ASIO_HAS_STD_CHRONO) #include +#include #if defined(BOOST_ASIO_HAS_BOOST_BIND) -# include # include #else // defined(BOOST_ASIO_HAS_BOOST_BIND) # include @@ -325,7 +325,7 @@ void system_timer_thread_test() boost::asio::system_timer t2(ios); int count = 0; - boost::thread th(bindns::bind(io_service_run, &ios)); + boost::asio::detail::thread th(bindns::bind(io_service_run, &ios)); t2.expires_from_now(chronons::seconds(2)); t2.wait(); diff --git a/test/windows/random_access_handle.cpp b/test/windows/random_access_handle.cpp index 7fd145f1..480d747c 100644 --- a/test/windows/random_access_handle.cpp +++ b/test/windows/random_access_handle.cpp @@ -49,7 +49,7 @@ void test() io_service ios; char mutable_char_buffer[128] = ""; const char const_char_buffer[128] = ""; - boost::uint64_t offset = 0; + boost::asio::uint64_t offset = 0; archetypes::lazy_handler lazy; boost::system::error_code ec;