From 3a28e999af2878f010d50f3a252baba8cc7fb6d0 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 7 Sep 2017 07:39:52 -0700 Subject: [PATCH] Update for Net-TS Asio (API Change): fix #769 The following classes are removed: * handler_type * async_result * async_completion * is_dynamic_buffer * is_const_buffer_sequence * is_mutable_buffer_sequence * handler_alloc Actions Required: * Use BOOST_ASIO_HANDLER_TYPE instead of handler_type * Use BOOST_ASIO_INITFN_RESULT_TYPE instead of async_result * Use boost::asio::async_completion * Use boost::asio::is_dynamic_buffer * Use boost::asio::is_const_buffer_sequence * Use boost::asio::is_mutable_buffer_sequence * boost::asio::associated_allocator_t replaces handler_alloc --- CHANGELOG.md | 18 + CMakeLists.txt | 2 +- doc/images/message.png | Bin 44322 -> 44093 bytes doc/qbk/00_main.qbk | 2 +- doc/qbk/03_core/1_asio.qbk | 8 +- doc/qbk/03_core/2_streams.qbk | 5 +- doc/qbk/03_core/3_buffers.qbk | 131 ++--- doc/qbk/03_core/5_composed.qbk | 53 +- doc/qbk/04_http/03_streams.qbk | 6 +- doc/qbk/04_http/08_chunked_encoding.qbk | 2 +- doc/qbk/06_websocket/1_streams.qbk | 4 +- doc/qbk/06_websocket/3_client.qbk | 2 +- doc/qbk/06_websocket/8_notes.qbk | 11 +- doc/qbk/07_concepts/DynamicBuffer.qbk | 2 +- doc/qbk/07_concepts/Fields.qbk | 2 +- doc/qbk/08_design.qbk | 2 +- doc/qbk/08_design/1_http_message.qbk | 8 +- doc/qbk/08_design/3_websocket_zaphoyd.qbk | 2 +- doc/qbk/quickref.xml | 10 +- doc/source.dox | 4 +- .../server-flex/advanced_server_flex.cpp | 217 ++++---- example/advanced/server/advanced_server.cpp | 123 +++-- example/common/detect_ssl.hpp | 95 ++-- example/common/session_alloc.hpp | 509 ++++++++---------- example/common/ssl_stream.hpp | 25 +- example/common/write_msg.hpp | 230 -------- example/doc/http_examples.hpp | 37 +- example/echo-op/echo_op.cpp | 144 +++-- .../async-ssl/http_client_async_ssl.cpp | 25 +- .../http/client/async/http_client_async.cpp | 27 +- .../client/coro-ssl/http_client_coro_ssl.cpp | 20 +- example/http/client/coro/http_client_coro.cpp | 20 +- example/http/client/crawl/http_crawl.cpp | 164 +++--- .../client/sync-ssl/http_client_sync_ssl.cpp | 12 +- example/http/client/sync/http_client_sync.cpp | 12 +- .../async-ssl/http_server_async_ssl.cpp | 76 +-- .../http/server/async/http_server_async.cpp | 56 +- .../server/coro-ssl/http_server_coro_ssl.cpp | 28 +- example/http/server/coro/http_server_coro.cpp | 28 +- example/http/server/fast/http_server_fast.cpp | 18 +- example/http/server/flex/http_server_flex.cpp | 116 ++-- .../http/server/small/http_server_small.cpp | 12 +- .../http_server_stackless_ssl.cpp | 86 +-- .../stackless/http_server_stackless.cpp | 58 +- .../server/sync-ssl/http_server_sync_ssl.cpp | 10 +- example/http/server/sync/http_server_sync.cpp | 10 +- .../async-ssl/websocket_client_async_ssl.cpp | 25 +- .../client/async/websocket_client_async.cpp | 25 +- .../coro-ssl/websocket_client_coro_ssl.cpp | 20 +- .../client/coro/websocket_client_coro.cpp | 20 +- .../sync-ssl/websocket_client_sync_ssl.cpp | 12 +- .../client/sync/websocket_client_sync.cpp | 12 +- .../async-ssl/websocket_server_async_ssl.cpp | 74 +-- .../server/async/websocket_server_async.cpp | 64 ++- .../coro-ssl/websocket_server_coro_ssl.cpp | 28 +- .../server/coro/websocket_server_coro.cpp | 28 +- .../server/fast/websocket_server_fast.cpp | 101 ++-- .../websocket_server_stackless_ssl.cpp | 78 +-- .../stackless/websocket_server_stackless.cpp | 66 ++- .../sync-ssl/websocket_server_sync_ssl.cpp | 10 +- .../server/sync/websocket_server_sync.cpp | 10 +- include/boost/beast/core.hpp | 2 - include/boost/beast/core/async_result.hpp | 209 ------- include/boost/beast/core/bind_handler.hpp | 11 +- .../boost/beast/core/buffered_read_stream.hpp | 51 +- include/boost/beast/core/buffers_adapter.hpp | 6 +- include/boost/beast/core/buffers_prefix.hpp | 27 +- include/boost/beast/core/buffers_suffix.hpp | 10 +- .../boost/beast/core/buffers_to_string.hpp | 9 +- .../boost/beast/core/detail/bind_handler.hpp | 87 +-- .../boost/beast/core/detail/buffers_ref.hpp | 13 +- include/boost/beast/core/detail/ostream.hpp | 33 +- .../boost/beast/core/detail/type_traits.hpp | 130 +++-- include/boost/beast/core/flat_buffer.hpp | 4 +- .../boost/beast/core/flat_static_buffer.hpp | 4 +- include/boost/beast/core/handler_alloc.hpp | 162 ------ .../beast/core/impl/buffered_read_stream.ipp | 73 ++- .../boost/beast/core/impl/buffers_adapter.ipp | 77 +-- include/boost/beast/core/impl/buffers_cat.ipp | 26 +- .../boost/beast/core/impl/buffers_prefix.ipp | 36 +- .../boost/beast/core/impl/buffers_suffix.ipp | 40 +- include/boost/beast/core/impl/handler_ptr.ipp | 48 +- include/boost/beast/core/impl/read_size.ipp | 3 +- include/boost/beast/core/ostream.hpp | 5 +- include/boost/beast/core/type_traits.hpp | 189 +------ .../boost/beast/http/basic_dynamic_body.hpp | 3 +- include/boost/beast/http/basic_file_body.hpp | 18 +- include/boost/beast/http/basic_parser.hpp | 2 +- include/boost/beast/http/buffer_body.hpp | 2 +- include/boost/beast/http/chunk_encode.hpp | 6 +- .../boost/beast/http/detail/chunk_encode.hpp | 8 +- .../boost/beast/http/impl/basic_parser.ipp | 24 +- .../boost/beast/http/impl/chunk_encode.ipp | 8 +- include/boost/beast/http/impl/fields.ipp | 24 +- .../boost/beast/http/impl/file_body_win32.ipp | 72 ++- include/boost/beast/http/impl/read.ipp | 221 ++++---- include/boost/beast/http/impl/serializer.ipp | 14 +- include/boost/beast/http/impl/write.ipp | 209 +++---- include/boost/beast/http/read.hpp | 44 +- include/boost/beast/http/serializer.hpp | 20 +- include/boost/beast/http/span_body.hpp | 2 +- include/boost/beast/http/string_body.hpp | 12 +- include/boost/beast/http/type_traits.hpp | 4 +- include/boost/beast/http/vector_body.hpp | 2 +- include/boost/beast/http/write.hpp | 42 +- .../boost/beast/websocket/detail/frame.hpp | 4 +- include/boost/beast/websocket/detail/mask.hpp | 12 +- .../beast/websocket/detail/pausation.hpp | 30 +- .../beast/websocket/detail/pmd_extension.hpp | 26 +- .../beast/websocket/detail/utf8_checker.hpp | 11 +- include/boost/beast/websocket/impl/accept.ipp | 202 ++++--- include/boost/beast/websocket/impl/close.ipp | 69 ++- .../boost/beast/websocket/impl/handshake.ipp | 89 ++- include/boost/beast/websocket/impl/ping.ipp | 76 ++- include/boost/beast/websocket/impl/read.ipp | 203 ++++--- include/boost/beast/websocket/impl/stream.ipp | 5 +- .../boost/beast/websocket/impl/teardown.ipp | 54 +- include/boost/beast/websocket/impl/write.ipp | 93 ++-- include/boost/beast/websocket/ssl.hpp | 2 +- include/boost/beast/websocket/stream.hpp | 221 +++----- include/boost/beast/websocket/teardown.hpp | 4 +- test/beast/core/CMakeLists.txt | 2 - test/beast/core/Jamfile | 2 - test/beast/core/async_result.cpp | 42 -- test/beast/core/buffer_test.hpp | 20 +- test/beast/core/buffered_read_stream.cpp | 31 +- test/beast/core/buffers_adapter.cpp | 11 +- test/beast/core/buffers_cat.cpp | 15 +- test/beast/core/buffers_prefix.cpp | 16 +- test/beast/core/buffers_suffix.cpp | 16 +- test/beast/core/flat_buffer.cpp | 4 +- test/beast/core/flat_static_buffer.cpp | 6 +- test/beast/core/handler_alloc.cpp | 67 --- test/beast/core/multi_buffer.cpp | 3 +- test/beast/core/ostream.cpp | 8 +- test/beast/core/static_buffer.cpp | 6 +- test/beast/core/type_traits.cpp | 22 +- test/beast/http/basic_parser.cpp | 20 +- test/beast/http/chunk_encode.cpp | 8 +- test/beast/http/dynamic_body.cpp | 14 +- test/beast/http/file_body.cpp | 7 +- test/beast/http/message_fuzz.hpp | 20 +- test/beast/http/parser.cpp | 2 +- test/beast/http/read.cpp | 48 +- test/beast/http/serializer.cpp | 4 +- test/beast/http/span_body.cpp | 4 +- test/beast/http/test_parser.hpp | 2 +- test/beast/http/write.cpp | 62 ++- test/beast/websocket/accept.cpp | 16 +- test/beast/websocket/close.cpp | 82 +-- test/beast/websocket/handshake.cpp | 2 +- test/beast/websocket/ping.cpp | 74 +-- test/beast/websocket/read.cpp | 88 +-- test/beast/websocket/stream.cpp | 6 +- test/beast/websocket/test.hpp | 42 +- test/beast/websocket/utf8_checker.cpp | 10 +- test/beast/websocket/write.cpp | 70 +-- test/bench/buffers/bench_buffers.cpp | 12 +- test/bench/parser/bench_parser.cpp | 10 +- test/bench/parser/nodejs_parser.hpp | 10 +- test/bench/wsload/wsload.cpp | 41 +- test/doc/core_examples.cpp | 4 +- test/doc/core_snippets.cpp | 17 +- test/doc/exemplars.cpp | 2 +- test/doc/http_examples.cpp | 33 +- test/doc/http_snippets.cpp | 14 +- test/doc/websocket_snippets.cpp | 43 +- test/example/common/CMakeLists.txt | 1 - test/example/common/Jamfile | 1 - test/example/common/write_msg.cpp | 12 - .../include/boost/beast/test/sig_wait.hpp | 6 +- .../include/boost/beast/test/stream.hpp | 176 +++--- .../include/boost/beast/test/yield_to.hpp | 20 +- 173 files changed, 3214 insertions(+), 4138 deletions(-) delete mode 100644 example/common/write_msg.hpp delete mode 100644 include/boost/beast/core/async_result.hpp delete mode 100644 include/boost/beast/core/handler_alloc.hpp delete mode 100644 test/beast/core/async_result.cpp delete mode 100644 test/beast/core/handler_alloc.cpp delete mode 100644 test/example/common/write_msg.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index e9be3165..e3c01d3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +Version 125: + +API Changes: + +* Update for Net-TS Asio + +Actions Required: + +* Use BOOST_ASIO_HANDLER_TYPE instead of handler_type +* Use BOOST_ASIO_INITFN_RESULT_TYPE instead of async_result +* Use boost::asio::async_completion +* Use boost::asio::is_dynamic_buffer +* Use boost::asio::is_const_buffer_sequence +* Use boost::asio::is_mutable_buffer_sequence +* boost::asio::associated_allocator_t replaces handler_alloc + +-------------------------------------------------------------------------------- + Version 124: * Fix for a test matrix compiler diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f18d0bc..caf7a3fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,6 @@ if (MSVC) add_definitions (-D_WIN32_WINNT=0x0601) add_definitions (-D_SCL_SECURE_NO_WARNINGS=1) add_definitions (-D_CRT_SECURE_NO_WARNINGS=1) - add_definitions (-DBOOST_ASIO_NO_DEPRECATED=1) add_compile_options( /bigobj # large object file format @@ -75,6 +74,7 @@ get_filename_component (BOOST_ROOT ../../ ABSOLUTE) # VFALCO I want static but "b2 stage" builds a minimal set which excludes static add_definitions (-DBOOST_ALL_STATIC_LINK=1) +add_definitions (-DBOOST_ASIO_NO_DEPRECATED=1) add_definitions (-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1) add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1) add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=1) diff --git a/doc/images/message.png b/doc/images/message.png index 393ef30d469a31a17a275866861ee5fc032bd7e2..99f8a50e6b89ff67b71e5a3c4274af119e170574 100644 GIT binary patch delta 43330 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 delta 43593 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�B9(P<8*tUJoruxlwl8HY*-aa+2sQ>n=75 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∨Z=_heNuDpKPtPpwQRq87<1s+)B^pd z5vM|(uXA(eDn_+F@1Y^|CRCn+~3^#Q(isk5`DSp6#Im{ z+>4Knab>;TAXez{Hzz;eKhEO>^SZg>h6?rqx4$~f-DtCEy=wiH@;JW?_VaeXb2h%4 z^u0iGpRs4Pue8p)h$)=OmFLg>&`FEe_9(u_t(g}zC;RKGtD=`rS!U#44?nd*#<``o zl;iU})zofjj@vtVBX)}EUA2xZUctSz_1_&yqc=Sn z`!`$t*PI%o;6pe)BMc+D(kFBo3g!;vRb=yn6?vzA-Es_9r#yR_ zt(&VW$8DLX{!!xQLyKF}&Q|8K`}6iaZ}yD)yKHaN?EdrhsZZ0sZlAYtdTve5DYg7P zKi2#?Bjs)_(|&uO($Q4s<)U2^tDo`*v0v+W%d7+bZ%^B4frM0prNi`S=f2hRbz{5w!k#)JmnwN;h(0b*Z-1LFsO7qlss-A0ifdZYvbg2V%XtG&bVr#s-jjEf zxGm14_={^(M)$L@6=EB~yU(t+?AE!pXnDpJLC_o+Xu=IVp$1w5pd?&%GQQv->$`Wm z-(Ra(?!=)860KhpX}}^W`^YTk#sr_~;8lDVQqMD~6Y!W`BqFA7gwbHhg9X3y?FUoQJ=F9vr(7wWpKHDEQm z%=doF&S}aUQXZeK6)T zK6xfuR#x_1i?Ck+V%ly)($TK2u-CP}zp1WMb(gDL;-(6oP&=(CpL=n&&6f+#J8#ET zy;Ll6HLBWz?`DC#!pS5xNIh|cSI+2@HuK%yPyv+CHq>Wo(`d1vfv$OcFule04psBg8 z-=O>WJkw7&HnVA7hWXtzOV-haDH=47xVEPTq7@W|AS(nwn`c3;s|Ps`tOMNb1}PQ- z?JR5&aN;pB*)!il z25ooj@CWTIb(a4oHto;u%>LJ_zEx4#;+oI-)@=We ztxi9D6cskzhPrcI(~WIf6Pt+vD0z%zrJ zGxuV)Q}j%Q7J)_etMfC}QP!CvhZQ^&RnWuP1Dr3MI54zAVn9{E39dJ)|G)kLhQnNy WrZ+Nbb}=w8FnGH9xvX : Fields }; ``` -The start-line data members are replaced traditional accessors using -non-owning references to string buffers. The method is stored using -a simple integer instead of the entire string, for the case where -the method is recognized from the set of known verb strings. +The start-line data members are replaced by traditional accessors +using non-owning references to string buffers. The method is stored +using a simple integer instead of the entire string, for the case +where the method is recognized from the set of known verb strings. Now we add a requirement to the fields type: management of the corresponding string is delegated to the [*Fields] container, which can diff --git a/doc/qbk/08_design/3_websocket_zaphoyd.qbk b/doc/qbk/08_design/3_websocket_zaphoyd.qbk index 271b9ee3..945380cd 100644 --- a/doc/qbk/08_design/3_websocket_zaphoyd.qbk +++ b/doc/qbk/08_design/3_websocket_zaphoyd.qbk @@ -122,7 +122,7 @@ through the __asio_handler_invoke__ mechanism. The only requirement in Beast is that calls to asynchronous initiation functions are made from the same implicit or explicit strand. For -example, if the `io_service` associated with a `beast::websocket::stream` +example, if the `io_context` associated with a `beast::websocket::stream` is single threaded, this counts as an implicit strand and no performance costs associated with mutexes are incurred. diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index 837ac750..1a9239c8 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -174,9 +174,6 @@ Classes - async_completion - async_result - async_return_type basic_flat_buffer basic_multi_buffer buffered_read_stream @@ -197,9 +194,7 @@ flat_buffer flat_static_buffer flat_static_buffer_base - handler_alloc handler_ptr - handler_type iequal iless multi_buffer @@ -236,15 +231,12 @@ Type Traits get_lowest_layer - has_get_io_service + has_get_executor is_async_read_stream is_async_write_stream is_async_stream is_completion_handler - is_const_buffer_sequence - is_dynamic_buffer is_file - is_mutable_buffer_sequence is_sync_read_stream is_sync_stream is_sync_write_stream diff --git a/doc/source.dox b/doc/source.dox index 86e85dd7..4d9d07ad 100644 --- a/doc/source.dox +++ b/doc/source.dox @@ -285,7 +285,9 @@ INCLUDE_FILE_PATTERNS = PREDEFINED = \ BOOST_BEAST_DOXYGEN \ BOOST_BEAST_USE_POSIX_FILE=1 \ - BOOST_BEAST_USE_WIN32_FILE=1 + BOOST_BEAST_USE_WIN32_FILE=1 \ + BOOST_ASIO_INITFN_RESULT_TYPE(t,a)=void_or_deduced \ + GENERATING_DOCUMENTATION EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES diff --git a/example/advanced/server-flex/advanced_server_flex.cpp b/example/advanced/server-flex/advanced_server_flex.cpp index 5391b413..1531141a 100644 --- a/example/advanced/server-flex/advanced_server_flex.cpp +++ b/example/advanced/server-flex/advanced_server_flex.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -235,15 +236,16 @@ class websocket_session boost::beast::multi_buffer buffer_; protected: - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::asio::steady_timer timer_; public: // Construct the session explicit - websocket_session(boost::asio::io_service& ios) - : strand_(ios) - , timer_(ios, + websocket_session(boost::asio::io_context& ioc) + : strand_(ioc.get_executor()) + , timer_(ioc, (std::chrono::steady_clock::time_point::max)()) { } @@ -254,15 +256,17 @@ public: do_accept(http::request> req) { // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Accept the websocket handshake derived().ws().async_accept( req, - strand_.wrap(std::bind( - &websocket_session::on_accept, - derived().shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_accept, + derived().shared_from_this(), + std::placeholders::_1))); } // Called when the timer expires. @@ -273,15 +277,17 @@ public: return fail(ec, "timer"); // Verify that the timer really expired since the deadline may have moved. - if(timer_.expires_at() <= std::chrono::steady_clock::now()) + if(timer_.expiry() <= std::chrono::steady_clock::now()) derived().do_timeout(); // Wait on the timer timer_.async_wait( - strand_.wrap(std::bind( - &websocket_session::on_timer, - derived().shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_timer, + derived().shared_from_this(), + std::placeholders::_1))); } void @@ -302,16 +308,18 @@ public: do_read() { // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Read a message into our buffer derived().ws().async_read( buffer_, - strand_.wrap(std::bind( - &websocket_session::on_read, - derived().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_read, + derived().shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -336,11 +344,13 @@ public: derived().ws().text(derived().ws().got_text()); derived().ws().async_write( buffer_.data(), - strand_.wrap(std::bind( - &websocket_session::on_write, - derived().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_write, + derived().shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -378,7 +388,7 @@ public: explicit plain_websocket_session(tcp::socket socket) : websocket_session( - socket.get_io_service()) + socket.get_executor().context()) , ws_(std::move(socket)) { } @@ -412,15 +422,17 @@ public: close_ = true; // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Close the WebSocket Connection ws_.async_close( websocket::close_code::normal, - strand_.wrap(std::bind( - &plain_websocket_session::on_close, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &plain_websocket_session::on_close, + shared_from_this(), + std::placeholders::_1))); } void @@ -443,7 +455,8 @@ class ssl_websocket_session , public std::enable_shared_from_this { websocket::stream> ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; bool eof_ = false; public: @@ -451,9 +464,9 @@ public: explicit ssl_websocket_session(ssl_stream stream) : websocket_session( - stream.get_io_service()) + stream.get_executor().context()) , ws_(std::move(stream)) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { } @@ -483,14 +496,16 @@ public: eof_ = true; // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Perform the SSL shutdown ws_.next_layer().async_shutdown( - strand_.wrap(std::bind( - &ssl_websocket_session::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &ssl_websocket_session::on_shutdown, + shared_from_this(), + std::placeholders::_1))); } void @@ -630,10 +645,12 @@ class http_session http::async_write( self_.derived().stream(), msg_, - self_.strand_.wrap(std::bind( - &http_session::on_write, - self_.derived().shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &http_session::on_write, + self_.derived().shared_from_this(), + std::placeholders::_1))); } }; @@ -652,20 +669,21 @@ class http_session protected: boost::asio::steady_timer timer_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; public: // Construct the session http_session( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, boost::beast::flat_buffer buffer, std::string const& doc_root) : doc_root_(doc_root) , queue_(*this) - , timer_(ios, + , timer_(ioc, (std::chrono::steady_clock::time_point::max)()) - , strand_(ios) + , strand_(ioc.get_executor()) , buffer_(std::move(buffer)) { } @@ -674,17 +692,19 @@ public: do_read() { // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Read a request http::async_read( derived().stream(), buffer_, req_, - strand_.wrap(std::bind( - &http_session::on_read, - derived().shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &http_session::on_read, + derived().shared_from_this(), + std::placeholders::_1))); } // Called when the timer expires. @@ -695,15 +715,17 @@ public: return fail(ec, "timer"); // Verify that the timer really expired since the deadline may have moved. - if(timer_.expires_at() <= std::chrono::steady_clock::now()) + if(timer_.expiry() <= std::chrono::steady_clock::now()) return derived().do_timeout(); // Wait on the timer timer_.async_wait( - strand_.wrap(std::bind( - &http_session::on_timer, - derived().shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &http_session::on_timer, + derived().shared_from_this(), + std::placeholders::_1))); } void @@ -769,7 +791,8 @@ class plain_http_session , public std::enable_shared_from_this { tcp::socket socket_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; public: // Create the http_session @@ -778,11 +801,11 @@ public: boost::beast::flat_buffer buffer, std::string const& doc_root) : http_session( - socket.get_io_service(), + socket.get_executor().context(), std::move(buffer), doc_root) , socket_(std::move(socket)) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) { } @@ -838,7 +861,8 @@ class ssl_http_session , public std::enable_shared_from_this { ssl_stream stream_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; bool eof_ = false; public: @@ -849,11 +873,11 @@ public: boost::beast::flat_buffer buffer, std::string const& doc_root) : http_session( - socket.get_io_service(), + socket.get_executor().context(), std::move(buffer), doc_root) , stream_(std::move(socket), ctx) - , strand_(stream_.get_io_service()) + , strand_(stream_.get_executor()) { } @@ -880,18 +904,20 @@ public: on_timer({}); // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Perform the SSL handshake // Note, this is the buffered version of the handshake. stream_.async_handshake( ssl::stream_base::server, buffer_.data(), - strand_.wrap(std::bind( - &ssl_http_session::on_handshake, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &ssl_http_session::on_handshake, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void on_handshake( @@ -917,14 +943,16 @@ public: eof_ = true; // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Perform the SSL shutdown stream_.async_shutdown( - strand_.wrap(std::bind( - &ssl_http_session::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &ssl_http_session::on_shutdown, + shared_from_this(), + std::placeholders::_1))); } void @@ -962,7 +990,8 @@ class detect_session : public std::enable_shared_from_this { tcp::socket socket_; ssl::context& ctx_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; std::string const& doc_root_; boost::beast::flat_buffer buffer_; @@ -974,7 +1003,7 @@ public: std::string const& doc_root) : socket_(std::move(socket)) , ctx_(ctx) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) { } @@ -986,11 +1015,13 @@ public: async_detect_ssl( socket_, buffer_, - strand_.wrap(std::bind( - &detect_session::on_detect, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &detect_session::on_detect, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } @@ -1029,13 +1060,13 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, std::string const& doc_root) : ctx_(ctx) - , acceptor_(ios) - , socket_(ios) + , acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -1058,7 +1089,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -1120,13 +1151,13 @@ int main(int argc, char* argv[]) " advanced-server-flex 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -1136,7 +1167,7 @@ int main(int argc, char* argv[]) // Create and launch a listening port std::make_shared( - ios, + ioc, ctx, tcp::endpoint{address, port}, doc_root)->run(); @@ -1146,11 +1177,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/advanced/server/advanced_server.cpp b/example/advanced/server/advanced_server.cpp index c8d5b78e..da3f82ac 100644 --- a/example/advanced/server/advanced_server.cpp +++ b/example/advanced/server/advanced_server.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -214,7 +215,8 @@ fail(boost::system::error_code ec, char const* what) class websocket_session : public std::enable_shared_from_this { websocket::stream ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::asio::steady_timer timer_; boost::beast::multi_buffer buffer_; @@ -223,8 +225,8 @@ public: explicit websocket_session(tcp::socket socket) : ws_(std::move(socket)) - , strand_(ws_.get_io_service()) - , timer_(ws_.get_io_service(), + , strand_(ws_.get_executor()) + , timer_(ws_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()) { } @@ -239,15 +241,17 @@ public: on_timer({}); // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Accept the websocket handshake ws_.async_accept( req, - strand_.wrap(std::bind( - &websocket_session::on_accept, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_accept, + shared_from_this(), + std::placeholders::_1))); } // Called when the timer expires. @@ -258,7 +262,7 @@ public: return fail(ec, "timer"); // Verify that the timer really expired since the deadline may have moved. - if(timer_.expires_at() <= std::chrono::steady_clock::now()) + if(timer_.expiry() <= std::chrono::steady_clock::now()) { // Closing the socket cancels all outstanding operations. They // will complete with boost::asio::error::operation_aborted @@ -269,10 +273,12 @@ public: // Wait on the timer timer_.async_wait( - strand_.wrap(std::bind( - &websocket_session::on_timer, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_timer, + shared_from_this(), + std::placeholders::_1))); } void @@ -293,16 +299,18 @@ public: do_read() { // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Read a message into our buffer ws_.async_read( buffer_, - strand_.wrap(std::bind( - &websocket_session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -327,11 +335,13 @@ public: ws_.text(ws_.got_text()); ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &websocket_session::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &websocket_session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -432,10 +442,12 @@ class http_session : public std::enable_shared_from_this http::async_write( self_.socket_, msg_, - self_.strand_.wrap(std::bind( - &http_session::on_write, - self_.shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &http_session::on_write, + self_.shared_from_this(), + std::placeholders::_1))); } }; @@ -449,7 +461,8 @@ class http_session : public std::enable_shared_from_this }; tcp::socket socket_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::asio::steady_timer timer_; boost::beast::flat_buffer buffer_; std::string const& doc_root_; @@ -463,8 +476,8 @@ public: tcp::socket socket, std::string const& doc_root) : socket_(std::move(socket)) - , strand_(socket_.get_io_service()) - , timer_(socket_.get_io_service(), + , strand_(socket_.get_executor()) + , timer_(socket_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()) , doc_root_(doc_root) , queue_(*this) @@ -486,14 +499,16 @@ public: do_read() { // Set the timer - timer_.expires_from_now(std::chrono::seconds(15)); + timer_.expires_after(std::chrono::seconds(15)); // Read a request http::async_read(socket_, buffer_, req_, - strand_.wrap(std::bind( - &http_session::on_read, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &http_session::on_read, + shared_from_this(), + std::placeholders::_1))); } // Called when the timer expires. @@ -504,7 +519,7 @@ public: return fail(ec, "timer"); // Verify that the timer really expired since the deadline may have moved. - if(timer_.expires_at() <= std::chrono::steady_clock::now()) + if(timer_.expiry() <= std::chrono::steady_clock::now()) { // Closing the socket cancels all outstanding operations. They // will complete with boost::asio::error::operation_aborted @@ -515,10 +530,12 @@ public: // Wait on the timer timer_.async_wait( - strand_.wrap(std::bind( - &http_session::on_timer, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &http_session::on_timer, + shared_from_this(), + std::placeholders::_1))); } void @@ -599,11 +616,11 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, std::string const& doc_root) - : acceptor_(ios) - , socket_(ios) + : acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -626,7 +643,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -687,17 +704,17 @@ int main(int argc, char* argv[]) " advanced-server 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create and launch a listening port std::make_shared( - ios, + ioc, tcp::endpoint{address, port}, doc_root)->run(); @@ -706,11 +723,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/common/detect_ssl.hpp b/example/common/detect_ssl.hpp index 9018ebdc..6d031aa6 100644 --- a/example/common/detect_ssl.hpp +++ b/example/common/detect_ssl.hpp @@ -61,7 +61,8 @@ is_ssl_handshake( ConstBufferSequence const& buffers) { // Make sure buffers meets the requirements - static_assert(boost::beast::is_const_buffer_sequence::value, + static_assert( + boost::asio::is_const_buffer_sequence::value, "ConstBufferSequence requirements not met"); // We need at least one byte to really do anything @@ -135,7 +136,8 @@ detect_ssl( // Make sure arguments meet the requirements static_assert(beast::is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); // Loop until an error occurs or we get a definitive answer @@ -219,15 +221,15 @@ detect_ssl( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class AsyncReadStream, class DynamicBuffer, class CompletionToken> -boost::beast::async_return_type< /*< The [link beast.ref.boost__beast__async_return_type `async_return_type`] customizes the return value based on the completion token >*/ +BOOST_ASIO_INITFN_RESULT_TYPE( /*< `BOOST_ASIO_INITFN_RESULT_TYPE` customizes the return value based on the completion token >*/ CompletionToken, - void(boost::beast::error_code, boost::tribool)> /*< This is the signature for the completion handler >*/ + void(boost::beast::error_code, boost::tribool)) /*< This is the signature for the completion handler >*/ async_detect_ssl( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -249,9 +251,9 @@ template< class AsyncReadStream, class DynamicBuffer, class CompletionToken> -boost::beast::async_return_type< +BOOST_ASIO_INITFN_RESULT_TYPE( CompletionToken, - void(boost::beast::error_code, boost::tribool)> + void(boost::beast::error_code, boost::tribool)) async_detect_ssl( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -262,26 +264,29 @@ async_detect_ssl( // Make sure arguments meet the requirements static_assert(beast::is_async_read_stream::value, "SyncReadStream requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); // This helper manages some of the handler's lifetime and // uses the result and handler specializations associated with // the completion token to help customize the return value. // - beast::async_completion< + boost::asio::async_completion< CompletionToken, void(beast::error_code, boost::tribool)> init{token}; // Create the composed operation and launch it. This is a constructor - // call followed by invocation of operator(). We use handler_type + // call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE // to convert the completion token into the correct handler type, // allowing user defined specializations of the async result template // to take effect. // - detect_ssl_op>{ - stream, buffer, init.completion_handler}( - beast::error_code{}, 0); + detect_ssl_op< + AsyncReadStream, + DynamicBuffer, + BOOST_ASIO_HANDLER_TYPE( + CompletionToken, void(beast::error_code, boost::tribool))>{ + stream, buffer, init.completion_handler}(beast::error_code{}, 0); // This hook lets the caller see a return value when appropriate. // For example this might return std::future if @@ -336,6 +341,35 @@ public: { } + // Associated allocator support. This is Asio's system for + // allowing the final completion handler to customize the + // memory allocation strategy used for composed operation + // states. A composed operation needs to use the same allocator + // as the final handler. These declarations achieve that. + + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(handler_); + } + + // Executor hook. This is Asio's system for customizing the + // manner in which asynchronous completion handlers are invoked. + // A composed operation needs to use the same executor to invoke + // intermediate completion handlers as that used to invoke the + // final handler. + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(stream_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor(handler_, stream_.get_executor()); + } + // Determines if the next asynchronous operation represents a // continuation of the asynchronous flow of control associated // with the final handler. If we are past step two, it means @@ -358,34 +392,6 @@ public: asio_handler_is_continuation(std::addressof(op->handler_)); } - // Handler hook forwarding. These free functions invoke the hooks - // associated with the final completion handler. In effect, they - // make the Asio implementation treat our composed operation the - // same way it would treat the final completion handler for the - // purpose of memory allocation and invocation. - // - // Our implementation just passes through the call to the hook - // associated with the final handler. - - friend void* asio_handler_allocate(std::size_t size, detect_ssl_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate(size, std::addressof(op->handler_)); - } - - friend void asio_handler_deallocate(void* p, std::size_t size, detect_ssl_op* op) - { - using boost::asio::asio_handler_deallocate; - return asio_handler_deallocate(p, size, std::addressof(op->handler_)); - } - - template - friend void asio_handler_invoke(Function&& f, detect_ssl_op* op) - { - using boost::asio::asio_handler_invoke; - return asio_handler_invoke(f, std::addressof(op->handler_)); - } - // Our main entry point. This will get called as our // intermediate operations complete. Definition below. // @@ -424,12 +430,13 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred) // We need to invoke the handler, but the guarantee // is that the handler will not be called before the // call to async_detect_ssl returns, so we must post - // the operation to the io_service. The helper function + // the operation to the executor. The helper function // `bind_handler` lets us bind arguments in a safe way // that preserves the type customization hooks of the // original handler. step_ = 1; - return stream_.get_io_service().post( + return boost::asio::post( + stream_.get_executor(), beast::bind_handler(std::move(*this), ec, 0)); } diff --git a/example/common/session_alloc.hpp b/example/common/session_alloc.hpp index 5730e235..40615e0a 100644 --- a/example/common/session_alloc.hpp +++ b/example/common/session_alloc.hpp @@ -10,21 +10,21 @@ #ifndef BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP #define BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP -#include +#include +#include #include -#include #include #include #include #include #include +namespace detail { + template class session_alloc_base { - template - class wrapped_handler; - +protected: class pool_t { using hook_type = @@ -78,23 +78,18 @@ class session_alloc_base boost::intrusive::constant_time_size< true>>::type; - Context* ctx_; std::size_t refs_ = 1; // shared count std::size_t high_ = 0; // highest used std::size_t size_ = 0; // size of buf_ char* buf_ = nullptr; // a large block list_type list_; // list of allocations - explicit - pool_t(Context* ctx) - : ctx_(ctx) - { - } + pool_t() = default; public: static pool_t& - construct(Context* ctx); + construct(); ~pool_t(); @@ -110,73 +105,178 @@ class session_alloc_base void dealloc(void* pv, std::size_t n); }; - - pool_t& pool_; - -public: - session_alloc_base& operator=(session_alloc_base const&) = delete; - - ~session_alloc_base() - { - pool_.release(); - } - - session_alloc_base() - : pool_(pool_t::construct(nullptr)) - { - static_assert(std::is_same::value, - "Context requirements not met"); - } - - session_alloc_base(session_alloc_base const& other) - : pool_(other.pool_.addref()) - { - } - - template, - typename std::decay::type - >::value>::type> - explicit - session_alloc_base(DeducedContext& ctx) - : pool_(pool_t::construct(std::addressof(ctx))) - { - static_assert(! std::is_same::value, - "Context requirements not met"); - } - - template - wrapped_handler::type> - wrap(Handler&& handler) - { - return wrapped_handler< - typename std::decay::type>( - std::forward(handler), *this); - } - -protected: - void* - alloc(std::size_t n) - { - return pool_.alloc(n); - } - - void - dealloc(void* p, std::size_t n) - { - pool_.dealloc(p, n); - } }; +template +auto +session_alloc_base:: +pool_t:: +construct() -> + pool_t& +{ + return *(new pool_t); +} + +template +session_alloc_base:: +pool_t:: +~pool_t() +{ + BOOST_ASSERT(list_.size() == 0); + if(buf_) + delete[] buf_; +} + +template +auto +session_alloc_base:: +pool_t:: +addref() -> + pool_t& +{ + ++refs_; + return *this; +} + +template +void +session_alloc_base:: +pool_t:: +release() +{ + if(--refs_) + return; + delete this; +} + +template +void* +session_alloc_base:: +pool_t:: +alloc(std::size_t n) +{ + if(list_.empty() && size_ < high_) + { + if(buf_) + delete[] buf_; + buf_ = new char[high_]; + size_ = high_; + } + if(buf_) + { + char* end; + std::size_t used; + if(list_.empty()) + { + end = buf_; + used = sizeof(element) + n; + } + else + { + end = list_.back().end(); + used = list_.back().used() + + sizeof(element) + n; + } + if(end >= buf_ && end + + sizeof(element) + n <= buf_ + size_) + { + auto& e = *new(end) element{n, used}; + list_.push_back(e); + high_ = (std::max)(high_, used); + return e.data(); + } + } + std::size_t const used = + sizeof(element) + n + ( + buf_ && ! list_.empty() ? + list_.back().used() : 0); + auto& e = *new(new char[sizeof(element) + n]) element{n, used}; + list_.push_back(e); + high_ = (std::max)(high_, used); + return e.data(); +} + +template +void +session_alloc_base:: +pool_t:: +dealloc(void* pv, std::size_t n) +{ + auto& e = *(reinterpret_cast(pv) - 1); + BOOST_ASSERT(e.size() == n); + if( (e.end() > buf_ + size_) || + reinterpret_cast(&e) < buf_) + { + list_.erase(list_.iterator_to(e)); + e.~element(); + delete[] reinterpret_cast(&e); + return; + } + list_.erase(list_.iterator_to(e)); + e.~element(); +} + +} // detail + //------------------------------------------------------------------------------ -template -class session_alloc : public session_alloc_base +template +class session_alloc + : private detail::session_alloc_base { - template + template friend class session_alloc; + template + class wrapped_handler + { + // Can't friend partial specializations, + // so we just friend the whole thing. + template + friend struct boost::asio::associated_executor; + + Handler h_; + session_alloc alloc_; + + public: + wrapped_handler(wrapped_handler&&) = default; + wrapped_handler(wrapped_handler const&) = default; + + template + wrapped_handler( + DeducedHandler&& h, + session_alloc const& alloc) + : h_(std::forward(h)) + , alloc_(alloc) + { + } + + using allocator_type = session_alloc; + + allocator_type + get_allocator() const noexcept; + + template + void + operator()(Args&&... args) const + { + h_(std::forward(args)...); + } + + friend + bool + asio_handler_is_continuation(wrapped_handler* w) + { + using boost::asio::asio_handler_is_continuation; + return asio_handler_is_continuation(std::addressof(w->h_)); + } + }; + + using pool_t = typename + detail::session_alloc_base::pool_t; + + pool_t& pool_; + public: using value_type = T; using is_always_equal = std::false_type; @@ -193,21 +293,32 @@ public: using other = session_alloc; }; - session_alloc() = default; - session_alloc(session_alloc const&) = default; + session_alloc& operator=(session_alloc const&) = delete; + + ~session_alloc() + { + pool_.release(); + } + + session_alloc() + : pool_(pool_t::construct()) + { + } + + session_alloc(session_alloc const& other) noexcept + : pool_(other.pool_.addref()) + { + } template - session_alloc(session_alloc const& other) - : session_alloc_base(static_cast< - session_alloc_base const&>(other)) + session_alloc(session_alloc const& other) noexcept + : pool_(other.pool_) { } - explicit - session_alloc(Context& ctx) - : session_alloc_base(ctx) - { - } + template + wrapped_handler::type> + wrap(Handler&& handler); value_type* allocate(size_type n) @@ -257,209 +368,67 @@ public: { return ! (lhs == rhs); } + +protected: + void* + alloc(std::size_t n) + { + return pool_.alloc(n); + } + + void + dealloc(void* p, std::size_t n) + { + pool_.dealloc(p, n); + } }; //------------------------------------------------------------------------------ -template +template template -class session_alloc_base::wrapped_handler +auto +session_alloc:: +wrapped_handler:: +get_allocator() const noexcept -> + allocator_type { - Handler h_; - session_alloc_base alloc_; - - void* - alloc(std::size_t size) - { - return alloc_.alloc(size); - } - - void - dealloc(void* p, std::size_t size) - { - alloc_.dealloc(p, size); - } - -public: - wrapped_handler(wrapped_handler&&) = default; - wrapped_handler(wrapped_handler const&) = default; - - template - explicit - wrapped_handler(DeducedHandler&& h, - session_alloc_base const& alloc) - : h_(std::forward(h)) - , alloc_(alloc) - { - } - - template - void - operator()(Args&&... args) const - { - h_(std::forward(args)...); - } - - friend - void* - asio_handler_allocate( - std::size_t size, wrapped_handler* w) - { - return w->alloc(size); - } - - friend - void - asio_handler_deallocate( - void* p, std::size_t size, wrapped_handler* w) - { - w->dealloc(p, size); - } - - friend - bool - asio_handler_is_continuation(wrapped_handler* w) - { - using boost::asio::asio_handler_is_continuation; - return asio_handler_is_continuation(std::addressof(w->h_)); - } - - template - friend - void - asio_handler_invoke(F&& f, wrapped_handler* w) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(w->h_)); - } -}; + return alloc_; +} //------------------------------------------------------------------------------ -template +template +template auto -session_alloc_base:: -pool_t:: -construct(Context* ctx) -> - pool_t& +session_alloc:: +wrap(Handler&& handler) -> + wrapped_handler::type> { - using boost::asio::asio_handler_allocate; - return *new(asio_handler_allocate( - sizeof(pool_t), ctx)) pool_t{ctx}; + return wrapped_handler< + typename std::decay::type>( + std::forward(handler), *this); } -template -session_alloc_base:: -pool_t:: -~pool_t() +namespace boost { +namespace asio { +template +struct associated_executor< + session_alloc::wrapped_handler, Executor> { - BOOST_ASSERT(list_.size() == 0); - if(buf_) + using type = typename + associated_executor::type; + + static + type + get(session_alloc::wrapped_handler const& h, + Executor const& ex = Executor()) noexcept { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(buf_, size_, ctx_); + return associated_executor< + Handler, Executor>::get(h.h_, ex); } -} - -template -auto -session_alloc_base:: -pool_t:: -addref() -> - pool_t& -{ - ++refs_; - return *this; -} - -template -void -session_alloc_base:: -pool_t:: -release() -{ - if(--refs_) - return; - this->~pool_t(); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(this, sizeof(*this), ctx_); -} - -template -void* -session_alloc_base:: -pool_t:: -alloc(std::size_t n) -{ - if(list_.empty() && size_ < high_) - { - if(buf_) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(buf_, size_, ctx_); - } - using boost::asio::asio_handler_allocate; - buf_ = reinterpret_cast( - asio_handler_allocate(high_, ctx_)); - size_ = high_; - } - if(buf_) - { - char* end; - std::size_t used; - if(list_.empty()) - { - end = buf_; - used = sizeof(element) + n; - } - else - { - end = list_.back().end(); - used = list_.back().used() + - sizeof(element) + n; - } - if(end >= buf_ && end + - sizeof(element) + n <= buf_ + size_) - { - auto& e = *new(end) element{n, used}; - list_.push_back(e); - high_ = (std::max)(high_, used); - return e.data(); - } - } - std::size_t const used = - sizeof(element) + n + ( - buf_ && ! list_.empty() ? - list_.back().used() : 0); - using boost::asio::asio_handler_allocate; - auto& e = *new(asio_handler_allocate( - sizeof(element) + n, ctx_)) element{n, used}; - list_.push_back(e); - high_ = (std::max)(high_, used); - return e.data(); -} - -template -void -session_alloc_base:: -pool_t:: -dealloc(void* pv, std::size_t n) -{ - auto& e = *(reinterpret_cast(pv) - 1); - BOOST_ASSERT(e.size() == n); - if( (e.end() > buf_ + size_) || - reinterpret_cast(&e) < buf_) - { - list_.erase(list_.iterator_to(e)); - e.~element(); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - &e, sizeof(e) + n, ctx_); - return; - } - list_.erase(list_.iterator_to(e)); - e.~element(); -} +}; +} // asio +} // boost #endif diff --git a/example/common/ssl_stream.hpp b/example/common/ssl_stream.hpp index b4dabd2b..90245c43 100644 --- a/example/common/ssl_stream.hpp +++ b/example/common/ssl_stream.hpp @@ -52,9 +52,6 @@ public: /// Structure for use with deprecated impl_type. using impl_struct = typename stream_type::impl_struct; - /// (Deprecated: Use native_handle_type.) The underlying implementation type. - using impl_type = typename stream_type::impl_type; - /// The type of the next layer. using next_layer_type = typename stream_type::next_layer_type; @@ -64,14 +61,16 @@ public: ssl_stream( boost::asio::ip::tcp::socket socket, boost::asio::ssl::context& ctx) - : p_(new stream_type{socket.get_io_service(), ctx}) + : p_(new stream_type{ + socket.get_executor().context(), ctx}) , ctx_(&ctx) { p_->next_layer() = std::move(socket); } ssl_stream(ssl_stream&& other) - : p_(new stream_type(other.get_io_service(), *other.ctx_)) + : p_(new stream_type( + other.get_executor().context(), *other.ctx_)) , ctx_(other.ctx_) { using std::swap; @@ -80,8 +79,8 @@ public: ssl_stream& operator=(ssl_stream&& other) { - std::unique_ptr p( - new stream_type{other.get_io_service(), other.ctx_}); + std::unique_ptr p(new stream_type{ + other.get_executor().context(), other.ctx_}); using std::swap; swap(p_, p); swap(p_, other.p_); @@ -89,10 +88,10 @@ public: return *this; } - boost::asio::io_service& - get_io_service() + decltype(p_->get_executor()) + get_executor() noexcept { - return p_->get_io_service(); + return p_->get_executor(); } native_handle_type @@ -101,12 +100,6 @@ public: return p_->native_handle(); } - impl_type - impl() - { - return p_->impl(); - } - next_layer_type const& next_layer() const { diff --git a/example/common/write_msg.hpp b/example/common/write_msg.hpp deleted file mode 100644 index fad3dd16..00000000 --- a/example/common/write_msg.hpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_EXAMPLE_COMMON_WRITE_MSG_HPP -#define BOOST_BEAST_EXAMPLE_COMMON_WRITE_MSG_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace detail { - -/** Composed operation to send an HTTP message - - This implements the composed operation needed for the - @ref async_write_msg function. -*/ -template< - class AsyncWriteStream, - class Handler, - bool isRequest, class Body, class Fields> -class write_msg_op -{ - // This composed operation has a state which is not trivial - // to copy (msg) so we need to store the state in an allocated - // object. - // - struct data - { - // The stream we are writing to - AsyncWriteStream& stream; - - // The message we are sending. Note that this composed - // operation takes ownership of the message and destroys - // it when it is done. - // - boost::beast::http::message msg; - - // Serializer for the message - boost::beast::http::serializer sr; - - data( - Handler& handler, - AsyncWriteStream& stream_, - boost::beast::http::message&& msg_) - : stream(stream_) - , msg(std::move(msg_)) - , sr(msg) - { - boost::ignore_unused(handler); - } - }; - - // `handler_ptr` is a utility which helps to manage a composed - // operation's state. It is similar to a shared pointer, but - // it uses handler allocation hooks to allocate and free memory, - // and it also helps to meet Asio's deallocate-before-invocation - // guarantee. - // - boost::beast::handler_ptr d_; - -public: - // Asio can move and copy the handler, we support both - write_msg_op(write_msg_op&&) = default; - write_msg_op(write_msg_op const&) = default; - - // Constructor - // - // We take the handler as a template type to - // support both const and rvalue references. - // - template< - class DeducedHandler, - class... Args> - write_msg_op( - DeducedHandler&& h, - AsyncWriteStream& s, - Args&&... args) - : d_(std::forward(h), - s, std::forward(args)...) - { - } - - // Entry point - // - // The initiation function calls this to start the operation - // - void - operator()() - { - auto& d = *d_; - boost::beast::http::async_write( - d.stream, d.sr, std::move(*this)); - } - - // Completion handler - // - // This gets called when boost::beast::http::async_write completes - // - void - operator()(boost::beast::error_code ec) - { - d_.invoke(ec); - } - - // - // These hooks are necessary for Asio - // - // The meaning is explained in the Beast documentation - // - - friend - void* asio_handler_allocate( - std::size_t size, write_msg_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_msg_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - - friend - bool asio_handler_is_continuation(write_msg_op* op) - { - using boost::asio::asio_handler_is_continuation; - return asio_handler_is_continuation(std::addressof(op->d_.handler())); - } - - template - friend - void asio_handler_invoke(Function&& f, write_msg_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } -}; - -} // detail - -/** Write an HTTP message to a stream asynchronously - - This function is used to write a complete message to a stream asynchronously - using HTTP/1. The function call always returns immediately. The asynchronous - operation will continue until one of the following conditions is true: - - @li The entire message is written. - - @li An error occurs. - - This operation is implemented in terms of zero or more calls to the stream's - `async_write_some` function, and is known as a composed operation. - The program must ensure that the stream performs no other write operations - until this operation completes. The algorithm will use a temporary - @ref serializer to produce buffers. If the semantics of the message - indicate that the connection should be closed after the message is sent, - the error delivered by this function - will be @ref error::end_of_stream - - @param stream The stream to which the data is to be written. - The type must support the @b AsyncWriteStream concept. - - @param msg The message to write. The function will take ownership - of the object as if by move constrction. - - @param handler The handler to be called when the operation - completes. Copies will be made of the handler as required. - The equivalent function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. -*/ -template< - class AsyncWriteStream, - bool isRequest, class Body, class Fields, - class WriteHandler> -boost::beast::async_return_type -async_write_msg( - AsyncWriteStream& stream, - boost::beast::http::message&& msg, - WriteHandler&& handler) -{ - static_assert( - boost::beast::is_async_write_stream::value, - "AsyncWriteStream requirements not met"); - - static_assert(boost::beast::http::is_body::value, - "Body requirements not met"); - - static_assert(boost::beast::http::is_body_reader::value, - "BodyReader requirements not met"); - - boost::beast::async_completion init{handler}; - - ::detail::write_msg_op< - AsyncWriteStream, - boost::beast::handler_type, - isRequest, Body, Fields>{ - init.completion_handler, - stream, - std::move(msg)}(); - - return init.result.get(); -} - -#endif diff --git a/example/doc/http_examples.hpp b/example/doc/http_examples.hpp index e1437830..7e10e26f 100644 --- a/example/doc/http_examples.hpp +++ b/example/doc/http_examples.hpp @@ -62,7 +62,8 @@ send_expect_100_continue( static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); // Insert or replace the Expect field @@ -123,7 +124,8 @@ receive_expect_100_continue( static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); // Declare a parser for a request with a string body @@ -194,9 +196,6 @@ send_cgi_response( static_assert(is_sync_write_stream::value, "SyncWriteStream requirements not met"); - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - // Set up the response. We use the buffer_body type, // allowing serialization to use manually provided buffers. response res; @@ -293,7 +292,8 @@ void do_server_head( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirments not met"); // We deliver this payload for all GET requests @@ -386,7 +386,8 @@ do_head_request( // Do some type checking to be a good citizen static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirments not met"); // The interfaces we are using are low level and do not @@ -589,10 +590,6 @@ public: void operator()(error_code& ec, ConstBufferSequence const& buffers) const { - // These asio functions are needed to access a buffer's contents - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - // Error codes must be cleared on success ec = {}; @@ -600,15 +597,16 @@ public: std::size_t bytes_transferred = 0; // Loop over the buffer sequence - for(auto it = buffers.begin(); it != buffers.end(); ++ it) + for(auto it = boost::asio::buffer_sequence_begin(buffers); + it != boost::asio::buffer_sequence_end(buffers); ++it) { // This is the next buffer in the sequence boost::asio::const_buffer const buffer = *it; // Write it to the std::ostream os_.write( - buffer_cast(buffer), - buffer_size(buffer)); + reinterpret_cast(buffer.data()), + buffer.size()); // If the std::ostream fails, convert it to an error code if(os_.fail()) @@ -714,13 +712,12 @@ read_istream( if(is.rdbuf()->in_avail() > 0) { // Get a mutable buffer sequence for writing - auto const mb = buffer.prepare( + auto const b = buffer.prepare( static_cast(is.rdbuf()->in_avail())); // Now get everything we can from the istream buffer.commit(static_cast(is.readsome( - boost::asio::buffer_cast(mb), - boost::asio::buffer_size(mb)))); + reinterpret_cast(b.data()), b.size()))); } else if(buffer.size() == 0) { @@ -729,12 +726,10 @@ read_istream( if(! is.eof()) { // Get a mutable buffer sequence for writing - auto const mb = buffer.prepare(1024); + auto const b = buffer.prepare(1024); // Try to get more from the istream. This might block. - is.read( - boost::asio::buffer_cast(mb), - boost::asio::buffer_size(mb)); + is.read(reinterpret_cast(b.data()), b.size()); // If an error occurs on the istream then return it to the caller. if(is.fail() && ! is.eof()) diff --git a/example/echo-op/echo_op.cpp b/example/echo-op/echo_op.cpp index 6a9a329a..45024f3a 100644 --- a/example/echo-op/echo_op.cpp +++ b/example/echo-op/echo_op.cpp @@ -23,7 +23,7 @@ auto async_echo(AsyncStream& stream, CompletionToken&& token) //] - -> boost::beast::async_return_type; + -> BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::beast::error_code)); //[example_core_echo_op_2 @@ -61,14 +61,14 @@ async_echo(AsyncStream& stream, CompletionToken&& token) Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class AsyncStream, class CompletionToken> -boost::beast::async_return_type< /*< The [link beast.ref.boost__beast__async_return_type `async_return_type`] customizes the return value based on the completion token >*/ +BOOST_ASIO_INITFN_RESULT_TYPE( /*< `BOOST_ASIO_INITFN_RESULT_TYPE` customizes the return value based on the completion token >*/ CompletionToken, - void(boost::beast::error_code)> /*< This is the signature for the completion handler >*/ + void(boost::beast::error_code)) /*< This is the signature for the completion handler >*/ async_echo( AsyncStream& stream, CompletionToken&& token); @@ -95,11 +95,13 @@ class echo_op // The buffer used to hold the input and output data. // // We use a custom allocator for performance, this allows - // the implementation of the io_service to make efficient + // the implementation of the io_context to make efficient // re-use of memory allocated by composed operations during // a continuation. // - boost::asio::basic_streambuf> buffer; + boost::asio::basic_streambuf >:: + template rebind_alloc > buffer; // handler_ptr requires that the first parameter to the // contained object constructor is a reference to the @@ -108,7 +110,7 @@ class echo_op explicit state(Handler& handler, AsyncStream& stream_) : stream(stream_) , buffer((std::numeric_limits::max)(), - boost::beast::handler_alloc{handler}) + boost::asio::get_associated_allocator(handler)) { } }; @@ -116,14 +118,10 @@ class echo_op // The operation's data is kept in a cheap-to-copy smart // pointer container called `handler_ptr`. This efficiently // satisfies the CopyConstructible requirements of completion - // handlers. + // handlers with expensive-to-copy state. // - // `handler_ptr` uses these memory allocation hooks associated - // with the final completion handler, in order to allocate the - // storage for `state`: - // - // asio_handler_allocate - // asio_handler_deallocate + // `handler_ptr` uses the allocator associated with the final + // completion handler, in order to allocate the storage for `state`. // boost::beast::handler_ptr p_; @@ -144,30 +142,45 @@ public: { } + // Associated allocator support. This is Asio's system for + // allowing the final completion handler to customize the + // memory allocation strategy used for composed operation + // states. A composed operation needs to use the same allocator + // as the final handler. These declarations achieve that. + + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(p_.handler()); + } + + // Executor hook. This is Asio's system for customizing the + // manner in which asynchronous completion handlers are invoked. + // A composed operation needs to use the same executor to invoke + // intermediate completion handlers as that used to invoke the + // final handler. + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(p_->stream.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + p_.handler(), p_->stream.get_executor()); + } + + // (DEPRECATED) + template + friend bool asio_handler_is_continuation( + echo_op* op); + // The entry point for this handler. This will get called // as our intermediate operations complete. Definition below. // void operator()(boost::beast::error_code ec, std::size_t bytes_transferred); - - // The next four functions are required for our class - // to meet the requirements for composed operations. - // Definitions and exposition will follow. - - template - friend void asio_handler_invoke( - Function&& f, echo_op* op); - - template - friend void* asio_handler_allocate( - std::size_t size, echo_op* op); - - template - friend void asio_handler_deallocate( - void* p, std::size_t size, echo_op* op); - - template - friend bool asio_handler_is_continuation( - echo_op* op); }; //] @@ -226,44 +239,6 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred) //[example_core_echo_op_6 -// Handler hook forwarding. These free functions invoke the hooks -// associated with the final completion handler. In effect, they -// make the Asio implementation treat our composed operation the -// same way it would treat the final completion handler for the -// purpose of memory allocation and invocation. -// -// Our implementation just passes the call through to the hook -// associated with the final handler. The "using" statements are -// structured to permit argument dependent lookup. Always use -// `std::addressof` or its equivalent to pass the pointer to the -// handler, otherwise an unwanted overload of `operator&` may be -// called instead. - -template -void asio_handler_invoke( - Function&& f, echo_op* op) -{ - using boost::asio::asio_handler_invoke; - return asio_handler_invoke(f, std::addressof(op->p_.handler())); -} - -template -void* asio_handler_allocate( - std::size_t size, echo_op* op) -{ - using boost::asio::asio_handler_allocate; - return asio_handler_allocate(size, std::addressof(op->p_.handler())); -} - -template -void asio_handler_deallocate( - void* p, std::size_t size, echo_op* op) -{ - using boost::asio::asio_handler_deallocate; - return asio_handler_deallocate(p, size, - std::addressof(op->p_.handler())); -} - // Determines if the next asynchronous operation represents a // continuation of the asynchronous flow of control associated // with the final handler. If we are past step one, it means @@ -297,7 +272,7 @@ class echo_op; // Read a line and echo it back // template -boost::beast::async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::beast::error_code)) async_echo(AsyncStream& stream, CompletionToken&& token) { // Make sure stream meets the requirements. We use static_assert @@ -310,16 +285,20 @@ async_echo(AsyncStream& stream, CompletionToken&& token) // uses the result and handler specializations associated with // the completion token to help customize the return value. // - boost::beast::async_completion init{token}; + boost::asio::async_completion init{token}; // Create the composed operation and launch it. This is a constructor - // call followed by invocation of operator(). We use handler_type + // call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE // to convert the completion token into the correct handler type, // allowing user-defined specializations of the async_result template // to be used. // - echo_op>{ - stream, init.completion_handler}(boost::beast::error_code{}, 0); + echo_op< + AsyncStream, + BOOST_ASIO_HANDLER_TYPE( + CompletionToken, void(boost::beast::error_code))>{ + stream, + init.completion_handler}(boost::beast::error_code{}, 0); // This hook lets the caller see a return value when appropriate. // For example this might return std::future if @@ -333,16 +312,15 @@ async_echo(AsyncStream& stream, CompletionToken&& token) int main(int, char** argv) { - using address_type = boost::asio::ip::address; using socket_type = boost::asio::ip::tcp::socket; using endpoint_type = boost::asio::ip::tcp::endpoint; // Create a listening socket, accept a connection, perform // the echo, and then shut everything down and exit. - boost::asio::io_service ios; - socket_type sock{ios}; - boost::asio::ip::tcp::acceptor acceptor{ios}; - endpoint_type ep{address_type::from_string("0.0.0.0"), 0}; + boost::asio::io_context ioc; + socket_type sock{ioc}; + boost::asio::ip::tcp::acceptor acceptor{ioc}; + endpoint_type ep{boost::asio::ip::make_address("0.0.0.0"), 0}; acceptor.open(ep.protocol()); acceptor.bind(ep); acceptor.listen(); @@ -353,6 +331,6 @@ int main(int, char** argv) if(ec) std::cerr << argv[0] << ": " << ec.message() << std::endl; }); - ios.run(); + ioc.run(); return 0; } diff --git a/example/http/client/async-ssl/http_client_async_ssl.cpp b/example/http/client/async-ssl/http_client_async_ssl.cpp index 9b0cad1d..71a55cda 100644 --- a/example/http/client/async-ssl/http_client_async_ssl.cpp +++ b/example/http/client/async-ssl/http_client_async_ssl.cpp @@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this http::response res_; public: - // Resolver and stream require an io_service + // Resolver and stream require an io_context explicit - session(boost::asio::io_service& ios, ssl::context& ctx) - : resolver_(ios) - , stream_(ios, ctx) + session(boost::asio::io_context& ioc, ssl::context& ctx) + : resolver_(ioc) + , stream_(ioc, ctx) { } @@ -73,7 +73,9 @@ public: req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); // Look up the domain name - resolver_.async_resolve({host, port}, + resolver_.async_resolve( + host, + port, std::bind( &session::on_resolve, shared_from_this(), @@ -84,7 +86,7 @@ public: void on_resolve( boost::system::error_code ec, - tcp::resolver::iterator result) + tcp::resolver::results_type results) { if(ec) return fail(ec, "resolve"); @@ -92,7 +94,8 @@ public: // Make the connection on the IP address we get from a lookup boost::asio::async_connect( stream_.next_layer(), - result, + results.begin(), + results.end(), std::bind( &session::on_connect, shared_from_this(), @@ -202,8 +205,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -212,11 +215,11 @@ int main(int argc, char** argv) load_root_certificates(ctx); // Launch the asynchronous operation - std::make_shared(ios, ctx)->run(host, port, target); + std::make_shared(ioc, ctx)->run(host, port, target); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/client/async/http_client_async.cpp b/example/http/client/async/http_client_async.cpp index 6c3f9af5..c7d46468 100644 --- a/example/http/client/async/http_client_async.cpp +++ b/example/http/client/async/http_client_async.cpp @@ -46,11 +46,11 @@ class session : public std::enable_shared_from_this http::response res_; public: - // Resolver and socket require an io_service + // Resolver and socket require an io_context explicit - session(boost::asio::io_service& ios) - : resolver_(ios) - , socket_(ios) + session(boost::asio::io_context& ioc) + : resolver_(ioc) + , socket_(ioc) { } @@ -69,7 +69,9 @@ public: req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); // Look up the domain name - resolver_.async_resolve({host, port}, + resolver_.async_resolve( + host, + port, std::bind( &session::on_resolve, shared_from_this(), @@ -80,13 +82,16 @@ public: void on_resolve( boost::system::error_code ec, - tcp::resolver::iterator result) + tcp::resolver::results_type results) { if(ec) return fail(ec, "resolve"); // Make the connection on the IP address we get from a lookup - boost::asio::async_connect(socket_, result, + boost::asio::async_connect( + socket_, + results.begin(), + results.end(), std::bind( &session::on_connect, shared_from_this(), @@ -168,15 +173,15 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // Launch the asynchronous operation - std::make_shared(ios)->run(host, port, target); + std::make_shared(ioc)->run(host, port, target); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/client/coro-ssl/http_client_coro_ssl.cpp b/example/http/client/coro-ssl/http_client_coro_ssl.cpp index 91526163..98b5fbdd 100644 --- a/example/http/client/coro-ssl/http_client_coro_ssl.cpp +++ b/example/http/client/coro-ssl/http_client_coro_ssl.cpp @@ -46,23 +46,23 @@ do_session( std::string const& host, std::string const& port, std::string const& target, - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, boost::asio::yield_context yield) { boost::system::error_code ec; // These objects perform our I/O - tcp::resolver resolver{ios}; - ssl::stream stream{ios, ctx}; + tcp::resolver resolver{ioc}; + ssl::stream stream{ioc, ctx}; // Look up the domain name - auto const lookup = resolver.async_resolve({host, port}, yield[ec]); + auto const results = resolver.async_resolve(host, port, yield[ec]); if(ec) return fail(ec, "resolve"); // Make the connection on the IP address we get from a lookup - boost::asio::async_connect(stream.next_layer(), lookup, yield[ec]); + boost::asio::async_connect(stream.next_layer(), results.begin(), results.end(), yield[ec]); if(ec) return fail(ec, "connect"); @@ -126,8 +126,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -136,18 +136,18 @@ int main(int argc, char** argv) load_root_certificates(ctx); // Launch the asynchronous operation - boost::asio::spawn(ios, std::bind( + boost::asio::spawn(ioc, std::bind( &do_session, std::string(host), std::string(port), std::string(target), - std::ref(ios), + std::ref(ioc), std::ref(ctx), std::placeholders::_1)); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/client/coro/http_client_coro.cpp b/example/http/client/coro/http_client_coro.cpp index 8f5665a5..b076b2f7 100644 --- a/example/http/client/coro/http_client_coro.cpp +++ b/example/http/client/coro/http_client_coro.cpp @@ -42,22 +42,22 @@ do_session( std::string const& host, std::string const& port, std::string const& target, - boost::asio::io_service& ios, + boost::asio::io_context& ioc, boost::asio::yield_context yield) { boost::system::error_code ec; // These objects perform our I/O - tcp::resolver resolver{ios}; - tcp::socket socket{ios}; + tcp::resolver resolver{ioc}; + tcp::socket socket{ioc}; // Look up the domain name - auto const lookup = resolver.async_resolve({host, port}, yield[ec]); + auto const results = resolver.async_resolve(host, port, yield[ec]); if(ec) return fail(ec, "resolve"); // Make the connection on the IP address we get from a lookup - boost::asio::async_connect(socket, lookup, yield[ec]); + boost::asio::async_connect(socket, results.begin(), results.end(), yield[ec]); if(ec) return fail(ec, "connect"); @@ -114,21 +114,21 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // Launch the asynchronous operation - boost::asio::spawn(ios, std::bind( + boost::asio::spawn(ioc, std::bind( &do_session, std::string(host), std::string(port), std::string(target), - std::ref(ios), + std::ref(ioc), std::placeholders::_1)); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/client/crawl/http_crawl.cpp b/example/http/client/crawl/http_crawl.cpp index ed6708ce..bb620f1d 100644 --- a/example/http/client/crawl/http_crawl.cpp +++ b/example/http/client/crawl/http_crawl.cpp @@ -18,10 +18,11 @@ #include #include #include +#include #include #include +#include #include -#include #include #include #include @@ -43,16 +44,17 @@ namespace chrono = std::chrono; // from // This structure aggregates statistics on all the sites class crawl_report { - boost::asio::io_service& ios_; - boost::asio::io_service::strand strand_; + boost::asio::io_context& ioc_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; std::atomic index_; std::vector const& hosts_; std::size_t count_ = 0; public: - crawl_report(boost::asio::io_service& ios) - : ios_(ios) - , strand_(ios_) + crawl_report(boost::asio::io_context& ioc) + : ioc_(ioc) + , strand_(ioc_.get_executor()) , index_(0) , hosts_(urls_large_data()) { @@ -64,18 +66,19 @@ public: void aggregate(F const& f) { - ios_.post(strand_.wrap( - [&, f] - { - f(*this); - if(count_ % 100 == 0) + boost::asio::post( + strand_, + [&, f] { - std::cerr << - "Progress: " << count_ << " of " << hosts_.size() << "\n"; - //std::cerr << *this; - } - ++count_; - })); + f(*this); + if(count_ % 100 == 0) + { + std::cerr << + "Progress: " << count_ << " of " << hosts_.size() << "\n"; + //std::cerr << *this; + } + ++count_; + }); } // Returns the next host to check @@ -148,7 +151,8 @@ class worker : public std::enable_shared_from_this tcp::resolver resolver_; tcp::socket socket_; boost::asio::steady_timer timer_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; // (Must persist between reads) http::request req_; http::response res_; @@ -156,16 +160,16 @@ class worker : public std::enable_shared_from_this public: worker(worker&&) = default; - // Resolver and socket require an io_service + // Resolver and socket require an io_context worker( crawl_report& report, - boost::asio::io_service& ios) + boost::asio::io_context& ioc) : report_(report) - , resolver_(ios) - , socket_(ios) - , timer_(ios, + , resolver_(ioc) + , socket_(ioc) + , timer_(ioc, (chrono::steady_clock::time_point::max)()) - , strand_(ios) + , strand_(ioc.get_executor()) { // Set up the common fields of the request req_.version(11); @@ -200,7 +204,7 @@ public: } // Verify that the timer really expired since the deadline may have moved. - if(timer_.expires_at() <= chrono::steady_clock::now()) + if(timer_.expiry() <= chrono::steady_clock::now()) { socket_.shutdown(tcp::socket::shutdown_both, ec); socket_.close(ec); @@ -209,10 +213,12 @@ public: // Wait on the timer timer_.async_wait( - strand_.wrap(std::bind( - &worker::on_timer, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &worker::on_timer, + shared_from_this(), + std::placeholders::_1))); } void @@ -224,8 +230,7 @@ public: // nullptr means no more work if(! host) { - boost::system::error_code ec; - timer_.cancel(ec); + timer_.cancel_one(); return; } @@ -233,23 +238,26 @@ public: req_.set(http::field::host, host); // Set the timer - timer_.expires_from_now(chrono::seconds(timeout)); + timer_.expires_after(chrono::seconds(timeout)); // Set up an HTTP GET request message // Look up the domain name resolver_.async_resolve( - tcp::resolver::query{host, "http"}, - strand_.wrap(std::bind( - &worker::on_resolve, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + host, + "http", + boost::asio::bind_executor( + strand_, + std::bind( + &worker::on_resolve, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void on_resolve( boost::system::error_code ec, - tcp::resolver::iterator result) + tcp::resolver::results_type results) { if(ec) { @@ -262,16 +270,19 @@ public: } // Set the timer - timer_.expires_from_now(chrono::seconds(timeout)); + timer_.expires_after(chrono::seconds(timeout)); // Make the connection on the IP address we get from a lookup boost::asio::async_connect( socket_, - result, - strand_.wrap(std::bind( - &worker::on_connect, - shared_from_this(), - std::placeholders::_1))); + results.begin(), + results.end(), + boost::asio::bind_executor( + strand_, + std::bind( + &worker::on_connect, + shared_from_this(), + std::placeholders::_1))); } void @@ -288,17 +299,19 @@ public: } // Set the timer - timer_.expires_from_now(chrono::seconds(timeout)); + timer_.expires_after(chrono::seconds(timeout)); // Send the HTTP request to the remote host http::async_write( socket_, req_, - strand_.wrap(std::bind( - &worker::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &worker::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -319,18 +332,20 @@ public: } // Set the timer - timer_.expires_from_now(chrono::seconds(timeout)); + timer_.expires_after(chrono::seconds(timeout)); // Receive the HTTP response http::async_read( socket_, buffer_, res_, - strand_.wrap(std::bind( - &worker::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &worker::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -400,41 +415,41 @@ int main(int argc, char* argv[]) " http-crawl 100 1\n"; return EXIT_FAILURE; } - auto const threads = std::max(1, std::atoi(argv[1])); + auto const threads = std::max(1, std::atoi(argv[1])); - // The io_service is required for all I/O - boost::asio::io_service ios{1}; + // The io_context is required for all I/O + boost::asio::io_context ioc{1}; - // The work keeps io_service::run from returning - boost::optional work{ios}; + // The work keeps io_context::run from returning + auto work = boost::asio::make_work_guard(ioc); // The report holds the aggregated statistics - crawl_report report{ios}; + crawl_report report{ioc}; timer t; // Create and launch the worker threads. std::vector workers; workers.reserve(threads + 1); - for(std::size_t i = 0; i < threads; ++i) + for(int i = 0; i < threads; ++i) workers.emplace_back( [&report] { - // We use a separate io_service for each worker because + // We use a separate io_context for each worker because // the asio resolver simulates asynchronous operation using - // a dedicated worker thread per io_service, and we want to + // a dedicated worker thread per io_context, and we want to // do a lot of name resolutions in parallel. - boost::asio::io_service ios{1}; - std::make_shared(report, ios)->run(); - ios.run(); + boost::asio::io_context ioc{1}; + std::make_shared(report, ioc)->run(); + ioc.run(); }); - // Add another thread to run the main io_service which + // Add another thread to run the main io_context which // is used to aggregate the statistics workers.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); // Now block until all threads exit @@ -442,11 +457,10 @@ int main(int argc, char* argv[]) { auto& thread = workers[i]; - // If this is the last thread, destroy the + // If this is the last thread, reset the // work object so that it can return from run. - //if(&thread == &workers.back()) if(i == workers.size() - 1) - work = boost::none; + work.reset(); // Wait for the thread to exit thread.join(); diff --git a/example/http/client/sync-ssl/http_client_sync_ssl.cpp b/example/http/client/sync-ssl/http_client_sync_ssl.cpp index 9ed63742..54bb6d67 100644 --- a/example/http/client/sync-ssl/http_client_sync_ssl.cpp +++ b/example/http/client/sync-ssl/http_client_sync_ssl.cpp @@ -47,8 +47,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -57,14 +57,14 @@ int main(int argc, char** argv) load_root_certificates(ctx); // These objects perform our I/O - tcp::resolver resolver{ios}; - ssl::stream stream{ios, ctx}; + tcp::resolver resolver{ioc}; + ssl::stream stream{ioc, ctx}; // Look up the domain name - auto const lookup = resolver.resolve({host, port}); + auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - boost::asio::connect(stream.next_layer(), lookup); + boost::asio::connect(stream.next_layer(), results.begin(), results.end()); // Perform the SSL handshake stream.handshake(ssl::stream_base::client); diff --git a/example/http/client/sync/http_client_sync.cpp b/example/http/client/sync/http_client_sync.cpp index e56fdc62..09a3e04f 100644 --- a/example/http/client/sync/http_client_sync.cpp +++ b/example/http/client/sync/http_client_sync.cpp @@ -45,18 +45,18 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const target = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // These objects perform our I/O - tcp::resolver resolver{ios}; - tcp::socket socket{ios}; + tcp::resolver resolver{ioc}; + tcp::socket socket{ioc}; // Look up the domain name - auto const lookup = resolver.resolve({host, port}); + auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - boost::asio::connect(socket, lookup); + boost::asio::connect(socket, results.begin(), results.end()); // Set up an HTTP GET request message http::request req{http::verb::get, target, 11}; diff --git a/example/http/server/async-ssl/http_server_async_ssl.cpp b/example/http/server/async-ssl/http_server_async_ssl.cpp index 57e95d99..052f2e58 100644 --- a/example/http/server/async-ssl/http_server_async_ssl.cpp +++ b/example/http/server/async-ssl/http_server_async_ssl.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -244,18 +245,21 @@ class session : public std::enable_shared_from_this http::async_write( self_.stream_, *sp, - self_.strand_.wrap(std::bind( - &session::on_write, - self_.shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - ! sp->keep_alive()))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &session::on_write, + self_.shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + ! sp->keep_alive()))); } }; tcp::socket socket_; ssl::stream stream_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; std::string const& doc_root_; http::request req_; @@ -271,7 +275,7 @@ public: std::string const& doc_root) : socket_(std::move(socket)) , stream_(socket_, ctx) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) , lambda_(*this) { @@ -284,10 +288,12 @@ public: // Perform the SSL handshake stream_.async_handshake( ssl::stream_base::server, - strand_.wrap(std::bind( - &session::on_handshake, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_handshake, + shared_from_this(), + std::placeholders::_1))); } void @@ -304,11 +310,13 @@ public: { // Read a request http::async_read(stream_, buffer_, req_, - strand_.wrap(std::bind( - &session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -359,10 +367,12 @@ public: { // Perform the SSL shutdown stream_.async_shutdown( - strand_.wrap(std::bind( - &session::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_shutdown, + shared_from_this(), + std::placeholders::_1))); } void @@ -387,13 +397,13 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, std::string const& doc_root) : ctx_(ctx) - , acceptor_(ios) - , socket_(ios) + , acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -416,7 +426,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -478,13 +488,13 @@ int main(int argc, char* argv[]) " http-server-async-ssl 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -494,7 +504,7 @@ int main(int argc, char* argv[]) // Create and launch a listening port std::make_shared( - ios, + ioc, ctx, tcp::endpoint{address, port}, doc_root)->run(); @@ -504,11 +514,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/async/http_server_async.cpp b/example/http/server/async/http_server_async.cpp index a388e9ca..985618b1 100644 --- a/example/http/server/async/http_server_async.cpp +++ b/example/http/server/async/http_server_async.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -240,17 +241,20 @@ class session : public std::enable_shared_from_this http::async_write( self_.socket_, *sp, - self_.strand_.wrap(std::bind( - &session::on_write, - self_.shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - ! sp->keep_alive()))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &session::on_write, + self_.shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + ! sp->keep_alive()))); } }; tcp::socket socket_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; std::string const& doc_root_; http::request req_; @@ -264,7 +268,7 @@ public: tcp::socket socket, std::string const& doc_root) : socket_(std::move(socket)) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) , lambda_(*this) { @@ -282,11 +286,13 @@ public: { // Read a request http::async_read(socket_, buffer_, req_, - strand_.wrap(std::bind( - &session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -354,11 +360,11 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, std::string const& doc_root) - : acceptor_(ios) - , socket_(ios) + : acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -381,7 +387,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -442,17 +448,17 @@ int main(int argc, char* argv[]) " http-server-async 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create and launch a listening port std::make_shared( - ios, + ioc, tcp::endpoint{address, port}, doc_root)->run(); @@ -461,11 +467,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/coro-ssl/http_server_coro_ssl.cpp b/example/http/server/coro-ssl/http_server_coro_ssl.cpp index 5b16661e..3cc7ffb6 100644 --- a/example/http/server/coro-ssl/http_server_coro_ssl.cpp +++ b/example/http/server/coro-ssl/http_server_coro_ssl.cpp @@ -308,7 +308,7 @@ do_session( // Accepts incoming connections and launches the sessions void do_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, std::string const& doc_root, @@ -317,7 +317,7 @@ do_listen( boost::system::error_code ec; // Open the acceptor - tcp::acceptor acceptor(ios); + tcp::acceptor acceptor(ioc); acceptor.open(endpoint.protocol(), ec); if(ec) return fail(ec, "open"); @@ -328,19 +328,19 @@ do_listen( return fail(ec, "bind"); // Start listening for connections - acceptor.listen(boost::asio::socket_base::max_connections, ec); + acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) return fail(ec, "listen"); for(;;) { - tcp::socket socket(ios); + tcp::socket socket(ioc); acceptor.async_accept(socket, yield[ec]); if(ec) fail(ec, "accept"); else boost::asio::spawn( - acceptor.get_io_service(), + acceptor.get_executor().context(), std::bind( &do_session, std::move(socket), @@ -361,13 +361,13 @@ int main(int argc, char* argv[]) " http-server-coro-ssl 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -376,10 +376,10 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // Spawn a listening port - boost::asio::spawn(ios, + boost::asio::spawn(ioc, std::bind( &do_listen, - std::ref(ios), + std::ref(ioc), std::ref(ctx), tcp::endpoint{address, port}, doc_root, @@ -390,11 +390,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/coro/http_server_coro.cpp b/example/http/server/coro/http_server_coro.cpp index 81a8b1af..f2aa9148 100644 --- a/example/http/server/coro/http_server_coro.cpp +++ b/example/http/server/coro/http_server_coro.cpp @@ -293,7 +293,7 @@ do_session( // Accepts incoming connections and launches the sessions void do_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, std::string const& doc_root, boost::asio::yield_context yield) @@ -301,7 +301,7 @@ do_listen( boost::system::error_code ec; // Open the acceptor - tcp::acceptor acceptor(ios); + tcp::acceptor acceptor(ioc); acceptor.open(endpoint.protocol(), ec); if(ec) return fail(ec, "open"); @@ -312,19 +312,19 @@ do_listen( return fail(ec, "bind"); // Start listening for connections - acceptor.listen(boost::asio::socket_base::max_connections, ec); + acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) return fail(ec, "listen"); for(;;) { - tcp::socket socket(ios); + tcp::socket socket(ioc); acceptor.async_accept(socket, yield[ec]); if(ec) fail(ec, "accept"); else boost::asio::spawn( - acceptor.get_io_service(), + acceptor.get_executor().context(), std::bind( &do_session, std::move(socket), @@ -344,19 +344,19 @@ int main(int argc, char* argv[]) " http-server-coro 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Spawn a listening port - boost::asio::spawn(ios, + boost::asio::spawn(ioc, std::bind( &do_listen, - std::ref(ios), + std::ref(ioc), tcp::endpoint{address, port}, doc_root, std::placeholders::_1)); @@ -366,11 +366,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/fast/http_server_fast.cpp b/example/http/server/fast/http_server_fast.cpp index 9f857c1e..b667bec8 100644 --- a/example/http/server/fast/http_server_fast.cpp +++ b/example/http/server/fast/http_server_fast.cpp @@ -97,7 +97,7 @@ private: std::string doc_root_; // The socket for the currently connected client. - tcp::socket socket_{acceptor_.get_io_service()}; + tcp::socket socket_{acceptor_.get_executor().context()}; // The buffer for performing reads boost::beast::flat_static_buffer<8192> buffer_; @@ -110,7 +110,7 @@ private: // The timer putting a time limit on requests. boost::asio::basic_waitable_timer request_deadline_{ - acceptor_.get_io_service(), (std::chrono::steady_clock::time_point::max)()}; + acceptor_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()}; // The string-based response message. boost::optional>> string_response_; @@ -142,7 +142,7 @@ private: else { // Request must be fully processed within 60 seconds. - request_deadline_.expires_from_now( + request_deadline_.expires_after( std::chrono::seconds(60)); read_request(); @@ -288,7 +288,7 @@ private: void check_deadline() { // The deadline may have moved, so check it has really passed. - if (request_deadline_.expires_at() <= std::chrono::steady_clock::now()) + if (request_deadline_.expiry() <= std::chrono::steady_clock::now()) { // Close socket to cancel any outstanding operation. boost::beast::error_code ec; @@ -322,14 +322,14 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } - auto address = ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); unsigned short port = static_cast(std::atoi(argv[2])); std::string doc_root = argv[3]; int num_workers = std::atoi(argv[4]); bool spin = (std::strcmp(argv[5], "spin") == 0); - boost::asio::io_service ios{1}; - tcp::acceptor acceptor{ios, {address, port}}; + boost::asio::io_context ioc{1}; + tcp::acceptor acceptor{ioc, {address, port}}; std::list workers; for (int i = 0; i < num_workers; ++i) @@ -339,9 +339,9 @@ int main(int argc, char* argv[]) } if (spin) - for (;;) ios.poll(); + for (;;) ioc.poll(); else - ios.run(); + ioc.run(); } catch (const std::exception& e) { diff --git a/example/http/server/flex/http_server_flex.cpp b/example/http/server/flex/http_server_flex.cpp index 46084fbc..5614ec48 100644 --- a/example/http/server/flex/http_server_flex.cpp +++ b/example/http/server/flex/http_server_flex.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -255,12 +256,14 @@ class session http::async_write( self_.derived().stream(), *sp, - self_.strand_.wrap(std::bind( - &session::on_write, - self_.derived().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - ! sp->keep_alive()))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &session::on_write, + self_.derived().shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + ! sp->keep_alive()))); } }; @@ -270,19 +273,20 @@ class session send_lambda lambda_; protected: - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; public: // Take ownership of the buffer explicit session( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, boost::beast::flat_buffer buffer, std::string const& doc_root) : doc_root_(doc_root) , lambda_(*this) - , strand_(ios) + , strand_(ioc.get_executor()) , buffer_(std::move(buffer)) { } @@ -295,11 +299,13 @@ public: derived().stream(), buffer_, req_, - strand_.wrap(std::bind( - &session::on_read, - derived().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + derived().shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -352,7 +358,8 @@ class plain_session , public std::enable_shared_from_this { tcp::socket socket_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; public: // Create the session @@ -361,11 +368,11 @@ public: boost::beast::flat_buffer buffer, std::string const& doc_root) : session( - socket.get_io_service(), + socket.get_executor().context(), std::move(buffer), doc_root) , socket_(std::move(socket)) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) { } @@ -401,7 +408,8 @@ class ssl_session { tcp::socket socket_; ssl::stream stream_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; public: // Create the session @@ -411,12 +419,12 @@ public: boost::beast::flat_buffer buffer, std::string const& doc_root) : session( - socket.get_io_service(), + socket.get_executor().context(), std::move(buffer), doc_root) , socket_(std::move(socket)) , stream_(socket_, ctx) - , strand_(stream_.get_io_service()) + , strand_(stream_.get_executor()) { } @@ -436,11 +444,13 @@ public: stream_.async_handshake( ssl::stream_base::server, buffer_.data(), - strand_.wrap(std::bind( - &ssl_session::on_handshake, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &ssl_session::on_handshake, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void on_handshake( @@ -461,10 +471,12 @@ public: { // Perform the SSL shutdown stream_.async_shutdown( - strand_.wrap(std::bind( - &ssl_session::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &ssl_session::on_shutdown, + shared_from_this(), + std::placeholders::_1))); } void @@ -484,7 +496,8 @@ class detect_session : public std::enable_shared_from_this { tcp::socket socket_; ssl::context& ctx_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; std::string const& doc_root_; boost::beast::flat_buffer buffer_; @@ -496,7 +509,7 @@ public: std::string const& doc_root) : socket_(std::move(socket)) , ctx_(ctx) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) { } @@ -508,11 +521,13 @@ public: async_detect_ssl( socket_, buffer_, - strand_.wrap(std::bind( - &detect_session::on_detect, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &detect_session::on_detect, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } @@ -545,21 +560,22 @@ public: class listener : public std::enable_shared_from_this { ssl::context& ctx_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; tcp::acceptor acceptor_; tcp::socket socket_; std::string const& doc_root_; public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, std::string const& doc_root) : ctx_(ctx) - , strand_(ios) - , acceptor_(ios) - , socket_(ios) + , strand_(ioc.get_executor()) + , acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -582,7 +598,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -644,13 +660,13 @@ int main(int argc, char* argv[]) " http-server-sync 0.0.0.0 8080 .\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -660,7 +676,7 @@ int main(int argc, char* argv[]) // Create and launch a listening port std::make_shared( - ios, + ioc, ctx, tcp::endpoint{address, port}, doc_root)->run(); @@ -670,11 +686,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/small/http_server_small.cpp b/example/http/server/small/http_server_small.cpp index c719b2d0..248eb449 100644 --- a/example/http/server/small/http_server_small.cpp +++ b/example/http/server/small/http_server_small.cpp @@ -75,7 +75,7 @@ private: // The timer for putting a deadline on connection processing. boost::asio::basic_waitable_timer deadline_{ - socket_.get_io_service(), std::chrono::seconds(60)}; + socket_.get_executor().context(), std::chrono::seconds(60)}; // Asynchronously receive a complete request message. void @@ -231,16 +231,16 @@ main(int argc, char* argv[]) return EXIT_FAILURE; } - auto address = ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); unsigned short port = static_cast(std::atoi(argv[2])); - boost::asio::io_service ios{1}; + boost::asio::io_context ioc{1}; - tcp::acceptor acceptor{ios, {address, port}}; - tcp::socket socket{ios}; + tcp::acceptor acceptor{ioc, {address, port}}; + tcp::socket socket{ioc}; http_server(acceptor, socket); - ios.run(); + ioc.run(); } catch(std::exception const& e) { diff --git a/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp b/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp index ce037b58..eb3e7e88 100644 --- a/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp +++ b/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -247,18 +248,21 @@ class session http::async_write( self_.socket_, *sp, - self_.strand_.wrap(std::bind( - &session::loop, - self_.shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - ! sp->keep_alive()))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &session::loop, + self_.shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + ! sp->keep_alive()))); } }; tcp::socket socket_; ssl::stream stream_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; std::string const& doc_root_; http::request req_; @@ -274,7 +278,7 @@ public: std::string const& doc_root) : socket_(std::move(socket)) , stream_(socket_, ctx) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) , lambda_(*this) { @@ -300,12 +304,14 @@ public: // Perform the SSL handshake yield stream_.async_handshake( ssl::stream_base::server, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - 0, - false))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + 0, + false))); if(ec) return fail(ec, "handshake"); @@ -313,12 +319,14 @@ public: { // Read a request yield http::async_read(stream_, buffer_, req_, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - false))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + false))); if(ec == http::error::end_of_stream) { // The remote host closed the connection @@ -344,12 +352,14 @@ public: // Perform the SSL shutdown yield stream_.async_shutdown( - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - 0, - false))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + 0, + false))); if(ec) return fail(ec, "shutdown"); @@ -373,13 +383,13 @@ class listener public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, std::string const& doc_root) : ctx_(ctx) - , acceptor_(ios) - , socket_(ios) + , acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -402,7 +412,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -464,13 +474,13 @@ int main(int argc, char* argv[]) " http-server-stackless-ssl 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -480,7 +490,7 @@ int main(int argc, char* argv[]) // Create and launch a listening port std::make_shared( - ios, + ioc, ctx, tcp::endpoint{address, port}, doc_root)->run(); @@ -490,11 +500,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/stackless/http_server_stackless.cpp b/example/http/server/stackless/http_server_stackless.cpp index 2dc8d86c..936ac3f7 100644 --- a/example/http/server/stackless/http_server_stackless.cpp +++ b/example/http/server/stackless/http_server_stackless.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -244,17 +245,20 @@ class session http::async_write( self_.socket_, *sp, - self_.strand_.wrap(std::bind( - &session::loop, - self_.shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - ! sp->keep_alive()))); + boost::asio::bind_executor( + self_.strand_, + std::bind( + &session::loop, + self_.shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + ! sp->keep_alive()))); } }; tcp::socket socket_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; std::string const& doc_root_; http::request req_; @@ -268,7 +272,7 @@ public: tcp::socket socket, std::string const& doc_root) : socket_(std::move(socket)) - , strand_(socket_.get_io_service()) + , strand_(socket_.get_executor()) , doc_root_(doc_root) , lambda_(*this) { @@ -295,12 +299,14 @@ public: { // Read a request yield http::async_read(socket_, buffer_, req_, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2, - false))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + false))); if(ec == http::error::end_of_stream) { // The remote host closed the connection @@ -346,11 +352,11 @@ class listener public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, std::string const& doc_root) - : acceptor_(ios) - , socket_(ios) + : acceptor_(ioc) + , socket_(ioc) , doc_root_(doc_root) { boost::system::error_code ec; @@ -372,7 +378,7 @@ public: } // Start listening for connections - acceptor_.listen(boost::asio::socket_base::max_connections, ec); + acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -433,17 +439,17 @@ int main(int argc, char* argv[]) " http-server-stackless 0.0.0.0 8080 . 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - auto const threads = std::max(1, std::atoi(argv[4])); + auto const threads = std::max(1, std::atoi(argv[4])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create and launch a listening port std::make_shared( - ios, + ioc, tcp::endpoint{address, port}, doc_root)->run(); @@ -452,11 +458,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/http/server/sync-ssl/http_server_sync_ssl.cpp b/example/http/server/sync-ssl/http_server_sync_ssl.cpp index 98894711..d478a0f7 100644 --- a/example/http/server/sync-ssl/http_server_sync_ssl.cpp +++ b/example/http/server/sync-ssl/http_server_sync_ssl.cpp @@ -311,12 +311,12 @@ int main(int argc, char* argv[]) " http-server-sync-ssl 0.0.0.0 8080 .\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios{1}; + // The io_context is required for all I/O + boost::asio::io_context ioc{1}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -325,11 +325,11 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // The acceptor receives incoming connections - tcp::acceptor acceptor{ios, {address, port}}; + tcp::acceptor acceptor{ioc, {address, port}}; for(;;) { // This will receive the new connection - tcp::socket socket{ios}; + tcp::socket socket{ioc}; // Block until we get a connection acceptor.accept(socket); diff --git a/example/http/server/sync/http_server_sync.cpp b/example/http/server/sync/http_server_sync.cpp index 1e76873c..f2ed7331 100644 --- a/example/http/server/sync/http_server_sync.cpp +++ b/example/http/server/sync/http_server_sync.cpp @@ -298,19 +298,19 @@ int main(int argc, char* argv[]) " http-server-sync 0.0.0.0 8080 .\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); std::string const doc_root = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios{1}; + // The io_context is required for all I/O + boost::asio::io_context ioc{1}; // The acceptor receives incoming connections - tcp::acceptor acceptor{ios, {address, port}}; + tcp::acceptor acceptor{ioc, {address, port}}; for(;;) { // This will receive the new connection - tcp::socket socket{ios}; + tcp::socket socket{ioc}; // Block until we get a connection acceptor.accept(socket); diff --git a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp index e1ee6238..c6337ae6 100644 --- a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp +++ b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp @@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this std::string text_; public: - // Resolver and socket require an io_service + // Resolver and socket require an io_context explicit - session(boost::asio::io_service& ios, ssl::context& ctx) - : resolver_(ios) - , ws_(ios, ctx) + session(boost::asio::io_context& ioc, ssl::context& ctx) + : resolver_(ioc) + , ws_(ioc, ctx) { } @@ -70,7 +70,9 @@ public: text_ = text; // Look up the domain name - resolver_.async_resolve({host, port}, + resolver_.async_resolve( + host, + port, std::bind( &session::on_resolve, shared_from_this(), @@ -81,7 +83,7 @@ public: void on_resolve( boost::system::error_code ec, - tcp::resolver::iterator result) + tcp::resolver::results_type results) { if(ec) return fail(ec, "resolve"); @@ -89,7 +91,8 @@ public: // Make the connection on the IP address we get from a lookup boost::asio::async_connect( ws_.next_layer().next_layer(), - result, + results.begin(), + results.end(), std::bind( &session::on_connect, shared_from_this(), @@ -209,8 +212,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -219,11 +222,11 @@ int main(int argc, char** argv) load_root_certificates(ctx); // Launch the asynchronous operation - std::make_shared(ios, ctx)->run(host, port, text); + std::make_shared(ioc, ctx)->run(host, port, text); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/client/async/websocket_client_async.cpp b/example/websocket/client/async/websocket_client_async.cpp index 757a8fcd..e09f6a5b 100644 --- a/example/websocket/client/async/websocket_client_async.cpp +++ b/example/websocket/client/async/websocket_client_async.cpp @@ -45,11 +45,11 @@ class session : public std::enable_shared_from_this std::string text_; public: - // Resolver and socket require an io_service + // Resolver and socket require an io_context explicit - session(boost::asio::io_service& ios) - : resolver_(ios) - , ws_(ios) + session(boost::asio::io_context& ioc) + : resolver_(ioc) + , ws_(ioc) { } @@ -65,7 +65,9 @@ public: text_ = text; // Look up the domain name - resolver_.async_resolve({host, port}, + resolver_.async_resolve( + host, + port, std::bind( &session::on_resolve, shared_from_this(), @@ -76,7 +78,7 @@ public: void on_resolve( boost::system::error_code ec, - tcp::resolver::iterator result) + tcp::resolver::results_type results) { if(ec) return fail(ec, "resolve"); @@ -84,7 +86,8 @@ public: // Make the connection on the IP address we get from a lookup boost::asio::async_connect( ws_.next_layer(), - result, + results.begin(), + results.end(), std::bind( &session::on_connect, shared_from_this(), @@ -189,15 +192,15 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // Launch the asynchronous operation - std::make_shared(ios)->run(host, port, text); + std::make_shared(ioc)->run(host, port, text); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp index 066d7f49..6fed0d05 100644 --- a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp +++ b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp @@ -46,23 +46,23 @@ do_session( std::string const& host, std::string const& port, std::string const& text, - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, boost::asio::yield_context yield) { boost::system::error_code ec; // These objects perform our I/O - tcp::resolver resolver{ios}; - websocket::stream> ws{ios, ctx}; + tcp::resolver resolver{ioc}; + websocket::stream> ws{ioc, ctx}; // Look up the domain name - auto const lookup = resolver.async_resolve({host, port}, yield[ec]); + auto const results = resolver.async_resolve(host, port, yield[ec]); if(ec) return fail(ec, "resolve"); // Make the connection on the IP address we get from a lookup - boost::asio::async_connect(ws.next_layer().next_layer(), lookup, yield[ec]); + boost::asio::async_connect(ws.next_layer().next_layer(), results.begin(), results.end(), yield[ec]); if(ec) return fail(ec, "connect"); @@ -117,8 +117,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -127,18 +127,18 @@ int main(int argc, char** argv) load_root_certificates(ctx); // Launch the asynchronous operation - boost::asio::spawn(ios, std::bind( + boost::asio::spawn(ioc, std::bind( &do_session, std::string(host), std::string(port), std::string(text), - std::ref(ios), + std::ref(ioc), std::ref(ctx), std::placeholders::_1)); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/client/coro/websocket_client_coro.cpp b/example/websocket/client/coro/websocket_client_coro.cpp index d12b298a..5aa4c755 100644 --- a/example/websocket/client/coro/websocket_client_coro.cpp +++ b/example/websocket/client/coro/websocket_client_coro.cpp @@ -41,22 +41,22 @@ do_session( std::string const& host, std::string const& port, std::string const& text, - boost::asio::io_service& ios, + boost::asio::io_context& ioc, boost::asio::yield_context yield) { boost::system::error_code ec; // These objects perform our I/O - tcp::resolver resolver{ios}; - websocket::stream ws{ios}; + tcp::resolver resolver{ioc}; + websocket::stream ws{ioc}; // Look up the domain name - auto const lookup = resolver.async_resolve({host, port}, yield[ec]); + auto const results = resolver.async_resolve(host, port, yield[ec]); if(ec) return fail(ec, "resolve"); // Make the connection on the IP address we get from a lookup - boost::asio::async_connect(ws.next_layer(), lookup, yield[ec]); + boost::asio::async_connect(ws.next_layer(), results.begin(), results.end(), yield[ec]); if(ec) return fail(ec, "connect"); @@ -106,21 +106,21 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // Launch the asynchronous operation - boost::asio::spawn(ios, std::bind( + boost::asio::spawn(ioc, std::bind( &do_session, std::string(host), std::string(port), std::string(text), - std::ref(ios), + std::ref(ioc), std::placeholders::_1)); // Run the I/O service. The call will return when // the get operation is complete. - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp index fe388a17..6281ec7c 100644 --- a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp +++ b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp @@ -47,8 +47,8 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23_client}; @@ -57,14 +57,14 @@ int main(int argc, char** argv) load_root_certificates(ctx); // These objects perform our I/O - tcp::resolver resolver{ios}; - websocket::stream> ws{ios, ctx}; + tcp::resolver resolver{ioc}; + websocket::stream> ws{ioc, ctx}; // Look up the domain name - auto const lookup = resolver.resolve({host, port}); + auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - boost::asio::connect(ws.next_layer().next_layer(), lookup); + boost::asio::connect(ws.next_layer().next_layer(), results.begin(), results.end()); // Perform the SSL handshake ws.next_layer().handshake(ssl::stream_base::client); diff --git a/example/websocket/client/sync/websocket_client_sync.cpp b/example/websocket/client/sync/websocket_client_sync.cpp index 690630a2..bde16c56 100644 --- a/example/websocket/client/sync/websocket_client_sync.cpp +++ b/example/websocket/client/sync/websocket_client_sync.cpp @@ -44,18 +44,18 @@ int main(int argc, char** argv) auto const port = argv[2]; auto const text = argv[3]; - // The io_service is required for all I/O - boost::asio::io_service ios; + // The io_context is required for all I/O + boost::asio::io_context ioc; // These objects perform our I/O - tcp::resolver resolver{ios}; - websocket::stream ws{ios}; + tcp::resolver resolver{ioc}; + websocket::stream ws{ioc}; // Look up the domain name - auto const lookup = resolver.resolve({host, port}); + auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - boost::asio::connect(ws.next_layer(), lookup); + boost::asio::connect(ws.next_layer(), results.begin(), results.end()); // Perform the websocket handshake ws.handshake(host, "/"); diff --git a/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp b/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp index a3469d56..a08aceb5 100644 --- a/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp +++ b/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,8 @@ class session : public std::enable_shared_from_this { tcp::socket socket_; websocket::stream> ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; public: @@ -56,7 +58,7 @@ public: session(tcp::socket socket, ssl::context& ctx) : socket_(std::move(socket)) , ws_(socket_, ctx) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { } @@ -67,10 +69,12 @@ public: // Perform the SSL handshake ws_.next_layer().async_handshake( ssl::stream_base::server, - strand_.wrap(std::bind( - &session::on_handshake, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_handshake, + shared_from_this(), + std::placeholders::_1))); } void @@ -81,10 +85,12 @@ public: // Accept the websocket handshake ws_.async_accept( - strand_.wrap(std::bind( - &session::on_accept, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_accept, + shared_from_this(), + std::placeholders::_1))); } void @@ -103,11 +109,13 @@ public: // Read a message into our buffer ws_.async_read( buffer_, - strand_.wrap(std::bind( - &session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -128,11 +136,13 @@ public: ws_.text(ws_.got_text()); ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &session::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -164,12 +174,12 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint) : ctx_(ctx) - , acceptor_(ios) - , socket_(ios) + , acceptor_(ioc) + , socket_(ioc) { boost::system::error_code ec; @@ -191,7 +201,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -250,12 +260,12 @@ int main(int argc, char* argv[]) " websocket-server-async-ssl 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -264,18 +274,18 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // Create and launch a listening port - std::make_shared(ios, ctx, tcp::endpoint{address, port})->run(); + std::make_shared(ioc, ctx, tcp::endpoint{address, port})->run(); // Run the I/O service on the requested number of threads std::vector v; v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/async/websocket_server_async.cpp b/example/websocket/server/async/websocket_server_async.cpp index ae87fea5..afaafc52 100644 --- a/example/websocket/server/async/websocket_server_async.cpp +++ b/example/websocket/server/async/websocket_server_async.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,8 @@ fail(boost::system::error_code ec, char const* what) class session : public std::enable_shared_from_this { websocket::stream ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; public: @@ -50,7 +52,7 @@ public: explicit session(tcp::socket socket) : ws_(std::move(socket)) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { } @@ -60,10 +62,12 @@ public: { // Accept the websocket handshake ws_.async_accept( - strand_.wrap(std::bind( - &session::on_accept, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_accept, + shared_from_this(), + std::placeholders::_1))); } void @@ -82,11 +86,13 @@ public: // Read a message into our buffer ws_.async_read( buffer_, - strand_.wrap(std::bind( - &session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -107,11 +113,13 @@ public: ws_.text(ws_.got_text()); ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &session::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -142,10 +150,10 @@ class listener : public std::enable_shared_from_this public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint) - : acceptor_(ios) - , socket_(ios) + : acceptor_(ioc) + , socket_(ioc) { boost::system::error_code ec; @@ -167,7 +175,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -226,26 +234,26 @@ int main(int argc, char* argv[]) " websocket-server-async 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create and launch a listening port - std::make_shared(ios, tcp::endpoint{address, port})->run(); + std::make_shared(ioc, tcp::endpoint{address, port})->run(); // Run the I/O service on the requested number of threads std::vector v; v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp b/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp index ef522ace..b480557d 100644 --- a/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp +++ b/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp @@ -93,7 +93,7 @@ do_session( // Accepts incoming connections and launches the sessions void do_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, boost::asio::yield_context yield) @@ -101,7 +101,7 @@ do_listen( boost::system::error_code ec; // Open the acceptor - tcp::acceptor acceptor(ios); + tcp::acceptor acceptor(ioc); acceptor.open(endpoint.protocol(), ec); if(ec) return fail(ec, "open"); @@ -112,19 +112,19 @@ do_listen( return fail(ec, "bind"); // Start listening for connections - acceptor.listen(boost::asio::socket_base::max_connections, ec); + acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) return fail(ec, "listen"); for(;;) { - tcp::socket socket(ios); + tcp::socket socket(ioc); acceptor.async_accept(socket, yield[ec]); if(ec) fail(ec, "accept"); else boost::asio::spawn( - acceptor.get_io_service(), + acceptor.get_executor().context(), std::bind( &do_session, std::move(socket), @@ -144,12 +144,12 @@ int main(int argc, char* argv[]) " websocket-server-coro-ssl 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -158,10 +158,10 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // Spawn a listening port - boost::asio::spawn(ios, + boost::asio::spawn(ioc, std::bind( &do_listen, - std::ref(ios), + std::ref(ioc), std::ref(ctx), tcp::endpoint{address, port}, std::placeholders::_1)); @@ -171,11 +171,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/coro/websocket_server_coro.cpp b/example/websocket/server/coro/websocket_server_coro.cpp index ee36a2ec..85d2e9c5 100644 --- a/example/websocket/server/coro/websocket_server_coro.cpp +++ b/example/websocket/server/coro/websocket_server_coro.cpp @@ -80,14 +80,14 @@ do_session(tcp::socket& socket, boost::asio::yield_context yield) // Accepts incoming connections and launches the sessions void do_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, boost::asio::yield_context yield) { boost::system::error_code ec; // Open the acceptor - tcp::acceptor acceptor(ios); + tcp::acceptor acceptor(ioc); acceptor.open(endpoint.protocol(), ec); if(ec) return fail(ec, "open"); @@ -98,19 +98,19 @@ do_listen( return fail(ec, "bind"); // Start listening for connections - acceptor.listen(boost::asio::socket_base::max_connections, ec); + acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) return fail(ec, "listen"); for(;;) { - tcp::socket socket(ios); + tcp::socket socket(ioc); acceptor.async_accept(socket, yield[ec]); if(ec) fail(ec, "accept"); else boost::asio::spawn( - acceptor.get_io_service(), + acceptor.get_executor().context(), std::bind( &do_session, std::move(socket), @@ -129,18 +129,18 @@ int main(int argc, char* argv[]) " websocket-server-coro 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Spawn a listening port - boost::asio::spawn(ios, + boost::asio::spawn(ioc, std::bind( &do_listen, - std::ref(ios), + std::ref(ioc), tcp::endpoint{address, port}, std::placeholders::_1)); @@ -149,11 +149,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/fast/websocket_server_fast.cpp b/example/websocket/server/fast/websocket_server_fast.cpp index d0570465..f0654c6c 100644 --- a/example/websocket/server/fast/websocket_server_fast.cpp +++ b/example/websocket/server/fast/websocket_server_fast.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -113,14 +114,14 @@ do_sync_session(tcp::socket& socket) void do_sync_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint) { boost::system::error_code ec; - tcp::acceptor acceptor{ios, endpoint}; + tcp::acceptor acceptor{ioc, endpoint}; for(;;) { - tcp::socket socket{ios}; + tcp::socket socket{ioc}; acceptor.accept(socket, ec); if(ec) @@ -138,7 +139,8 @@ do_sync_listen( class async_session : public std::enable_shared_from_this { websocket::stream ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; public: @@ -146,7 +148,7 @@ public: explicit async_session(tcp::socket socket) : ws_(std::move(socket)) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { setup_stream(ws_); } @@ -162,10 +164,12 @@ public: res.set(http::field::server, "Boost.Beast.async/" + std::to_string(BOOST_BEAST_VERSION)); }, - strand_.wrap(std::bind( - &async_session::on_accept, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &async_session::on_accept, + shared_from_this(), + std::placeholders::_1))); } void @@ -184,11 +188,13 @@ public: // Read a message into our buffer ws_.async_read( buffer_, - strand_.wrap(std::bind( - &async_session::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &async_session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -209,11 +215,13 @@ public: ws_.text(ws_.got_text()); ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &async_session::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &async_session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); } void @@ -237,17 +245,18 @@ public: // Accepts incoming connections and launches the sessions class async_listener : public std::enable_shared_from_this { - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; tcp::acceptor acceptor_; tcp::socket socket_; public: async_listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint) - : strand_(ios) - , acceptor_(ios) - , socket_(ios) + : strand_(ioc.get_executor()) + , acceptor_(ioc) + , socket_(ioc) { boost::system::error_code ec; @@ -269,7 +278,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -291,10 +300,12 @@ public: { acceptor_.async_accept( socket_, - strand_.wrap(std::bind( - &async_listener::on_accept, - shared_from_this(), - std::placeholders::_1))); + boost::asio::bind_executor( + strand_, + std::bind( + &async_listener::on_accept, + shared_from_this(), + std::placeholders::_1))); } void @@ -354,13 +365,13 @@ do_coro_session(tcp::socket& socket, boost::asio::yield_context yield) void do_coro_listen( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint, boost::asio::yield_context yield) { boost::system::error_code ec; - tcp::acceptor acceptor(ios); + tcp::acceptor acceptor(ioc); acceptor.open(endpoint.protocol(), ec); if(ec) return fail(ec, "open"); @@ -369,13 +380,13 @@ do_coro_listen( if(ec) return fail(ec, "bind"); - acceptor.listen(boost::asio::socket_base::max_connections, ec); + acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if(ec) return fail(ec, "listen"); for(;;) { - tcp::socket socket(ios); + tcp::socket socket(ioc); acceptor.async_accept(socket, yield[ec]); if(ec) @@ -385,7 +396,7 @@ do_coro_listen( } boost::asio::spawn( - acceptor.get_io_service(), + acceptor.get_executor().context(), std::bind( &do_coro_session, std::move(socket), @@ -410,17 +421,17 @@ int main(int argc, char* argv[]) " starting-port+2 for coroutine.\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create sync port std::thread(std::bind( &do_sync_listen, - std::ref(ios), + std::ref(ioc), tcp::endpoint{ address, static_cast(port + 0u)} @@ -428,16 +439,16 @@ int main(int argc, char* argv[]) // Create async port std::make_shared( - ios, + ioc, tcp::endpoint{ address, static_cast(port + 1u)})->run(); // Create coro port - boost::asio::spawn(ios, + boost::asio::spawn(ioc, std::bind( &do_coro_listen, - std::ref(ios), + std::ref(ioc), tcp::endpoint{ address, static_cast(port + 2u)}, @@ -448,11 +459,11 @@ int main(int argc, char* argv[]) v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp b/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp index 7c94f59b..7162ab78 100644 --- a/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp +++ b/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,8 @@ class session { tcp::socket socket_; websocket::stream> ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; public: @@ -59,7 +61,7 @@ public: session(tcp::socket socket, ssl::context& ctx) : socket_(std::move(socket)) , ws_(socket_, ctx) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { } @@ -83,21 +85,25 @@ public: // Perform the SSL handshake yield ws_.next_layer().async_handshake( ssl::stream_base::server, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - 0))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + 0))); if(ec) return fail(ec, "handshake"); // Accept the websocket handshake yield ws_.async_accept( - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - 0))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + 0))); if(ec) return fail(ec, "accept"); @@ -106,11 +112,13 @@ public: // Read a message into our buffer yield ws_.async_read( buffer_, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); if(ec == websocket::error::closed) { // This indicates that the session was closed @@ -123,11 +131,13 @@ public: ws_.text(ws_.got_text()); yield ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); if(ec) return fail(ec, "write"); @@ -152,12 +162,12 @@ class listener public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint) : ctx_(ctx) - , acceptor_(ios) - , socket_(ios) + , acceptor_(ioc) + , socket_(ioc) { boost::system::error_code ec; @@ -179,7 +189,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -238,12 +248,12 @@ int main(int argc, char* argv[]) " websocket-server-async-ssl 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -252,18 +262,18 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // Create and launch a listening port - std::make_shared(ios, ctx, tcp::endpoint{address, port})->run(); + std::make_shared(ioc, ctx, tcp::endpoint{address, port})->run(); // Run the I/O service on the requested number of threads std::vector v; v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/stackless/websocket_server_stackless.cpp b/example/websocket/server/stackless/websocket_server_stackless.cpp index d76949ad..cc4eb252 100644 --- a/example/websocket/server/stackless/websocket_server_stackless.cpp +++ b/example/websocket/server/stackless/websocket_server_stackless.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,8 @@ class session , public std::enable_shared_from_this { websocket::stream ws_; - boost::asio::io_service::strand strand_; + boost::asio::strand< + boost::asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; public: @@ -53,7 +55,7 @@ public: explicit session(tcp::socket socket) : ws_(std::move(socket)) - , strand_(ws_.get_io_service()) + , strand_(ws_.get_executor()) { } @@ -75,11 +77,13 @@ public: { // Accept the websocket handshake yield ws_.async_accept( - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - 0))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + 0))); if(ec) return fail(ec, "accept"); @@ -88,11 +92,13 @@ public: // Read a message into our buffer yield ws_.async_read( buffer_, - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); if(ec == websocket::error::closed) { // This indicates that the session was closed @@ -105,11 +111,13 @@ public: ws_.text(ws_.got_text()); yield ws_.async_write( buffer_.data(), - strand_.wrap(std::bind( - &session::loop, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::bind_executor( + strand_, + std::bind( + &session::loop, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); if(ec) return fail(ec, "write"); @@ -133,10 +141,10 @@ class listener public: listener( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, tcp::endpoint endpoint) - : acceptor_(ios) - , socket_(ios) + : acceptor_(ioc) + , socket_(ioc) { boost::system::error_code ec; @@ -158,7 +166,7 @@ public: // Start listening for connections acceptor_.listen( - boost::asio::socket_base::max_connections, ec); + boost::asio::socket_base::max_listen_connections, ec); if(ec) { fail(ec, "listen"); @@ -217,26 +225,26 @@ int main(int argc, char* argv[]) " websocket-server-stackless 0.0.0.0 8080 1\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - auto const threads = std::max(1, std::atoi(argv[3])); + auto const threads = std::max(1, std::atoi(argv[3])); - // The io_service is required for all I/O - boost::asio::io_service ios{threads}; + // The io_context is required for all I/O + boost::asio::io_context ioc{threads}; // Create and launch a listening port - std::make_shared(ios, tcp::endpoint{address, port})->run(); + std::make_shared(ioc, tcp::endpoint{address, port})->run(); // Run the I/O service on the requested number of threads std::vector v; v.reserve(threads - 1); for(auto i = threads - 1; i > 0; --i) v.emplace_back( - [&ios] + [&ioc] { - ios.run(); + ioc.run(); }); - ios.run(); + ioc.run(); return EXIT_SUCCESS; } diff --git a/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp b/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp index 8328ec78..1e3f7332 100644 --- a/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp +++ b/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp @@ -87,11 +87,11 @@ int main(int argc, char* argv[]) " websocket-server-sync-ssl 0.0.0.0 8080\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - // The io_service is required for all I/O - boost::asio::io_service ios{1}; + // The io_context is required for all I/O + boost::asio::io_context ioc{1}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::sslv23}; @@ -100,11 +100,11 @@ int main(int argc, char* argv[]) load_server_certificate(ctx); // The acceptor receives incoming connections - tcp::acceptor acceptor{ios, {address, port}}; + tcp::acceptor acceptor{ioc, {address, port}}; for(;;) { // This will receive the new connection - tcp::socket socket{ios}; + tcp::socket socket{ioc}; // Block until we get a connection acceptor.accept(socket); diff --git a/example/websocket/server/sync/websocket_server_sync.cpp b/example/websocket/server/sync/websocket_server_sync.cpp index 8ba0f3f6..7a4878cf 100644 --- a/example/websocket/server/sync/websocket_server_sync.cpp +++ b/example/websocket/server/sync/websocket_server_sync.cpp @@ -79,18 +79,18 @@ int main(int argc, char* argv[]) " websocket-server-sync 0.0.0.0 8080\n"; return EXIT_FAILURE; } - auto const address = boost::asio::ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); - // The io_service is required for all I/O - boost::asio::io_service ios{1}; + // The io_context is required for all I/O + boost::asio::io_context ioc{1}; // The acceptor receives incoming connections - tcp::acceptor acceptor{ios, {address, port}}; + tcp::acceptor acceptor{ioc, {address, port}}; for(;;) { // This will receive the new connection - tcp::socket socket{ios}; + tcp::socket socket{ioc}; // Block until we get a connection acceptor.accept(socket); diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index 0cc3d457..620d42ad 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -12,7 +12,6 @@ #include -#include #include #include #include @@ -28,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/beast/core/async_result.hpp b/include/boost/beast/core/async_result.hpp deleted file mode 100644 index 47d7aa92..00000000 --- a/include/boost/beast/core/async_result.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_ASYNC_COMPLETION_HPP -#define BOOST_BEAST_ASYNC_COMPLETION_HPP - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { - -/** An interface for customising the behaviour of an asynchronous initiation function. - - This class is used for determining: - - @li The concrete completion handler type to be called at the end of the - asynchronous operation; - - @li the initiating function return type; and - - @li how the return value of the initiating function is obtained. - - The trait allows the handler and return types to be determined at the point - where the specific completion handler signature is known. - - This template takes advantage of specializations of both - `boost::asio::async_result` and `boost::asio::handler_type` for user-defined - completion token types. The primary template assumes that the - @b CompletionToken is the completion handler. - - @par Example - - The example shows how to define an asynchronous initiation function - whose completion handler receives an error code: - - @code - template< - class AsyncStream, // A stream supporting asynchronous read and write - class Handler // The handler to call with signature void(error_code) - > - async_return_type< // This provides the return type customization - Handler, void(error_code)> - do_async( - AsyncStream& stream, // The stream to work on - Handler&& handler) // Could be an rvalue or const reference - { - // Make sure we have an async stream - static_assert(is_async_stream::value, - "AsyncStream requirements not met"); - - // This helper converts the handler into the real handler type - async_completion init{handler}; - - ... // Create and invoke the composed operation - - // This provides the return value and executor customization - return init.result.get(); - } - @endcode - - @see @ref async_completion, @ref async_return_type, @ref handler_type -*/ -template -class async_result -{ - BOOST_STATIC_ASSERT( - ! std::is_reference::value); - - boost::asio::async_result::type> impl_; - - async_result(async_result const&) = delete; - async_result& operator=(async_result const&) = delete; - -public: - /// The concrete completion handler type for the specific signature. - using completion_handler_type = - typename boost::asio::handler_type< - CompletionToken, Signature>::type; - - /// The return type of the initiating function. - using return_type = - typename boost::asio::async_result< - completion_handler_type>::type; - - /** Construct an async result from a given handler. - - When using a specalised async_result, the constructor has - an opportunity to initialise some state associated with the - completion handler, which is then returned from the initiating - function. - */ - explicit - async_result(completion_handler_type& h) - : impl_(h) - { - } - - /// Obtain the value to be returned from the initiating function. - return_type - get() - { - return impl_.get(); - } -}; - -/** Helper for customizing the return type of asynchronous initiation functions. - - This class template is used to transform caller-provided completion - handlers in calls to asynchronous initiation functions. The transformation - allows customization of the return type of the initiating function, and the - function signature of the final handler. - - Example: - @code - ... - template - typename async_completion::result_type - async_initfn(..., CompletionToken&& handler) - { - async_completion completion{handler}; - ... - return completion.result.get(); - } - @endcode - - @tparam CompletionToken Specifies the model used to obtain the result of - the asynchronous operation. - - @tparam Signature The call signature for the completion handler type invoked - on completion of the asynchronous operation. - - @note See - Working Draft, C++ Extensions for Networking - - @see @ref async_return_type, @ref handler_type -*/ -template -struct async_completion -{ - /** The type of the final handler called by the asynchronous initiation function. - - Objects of this type will be callable with the specified signature. - */ - using completion_handler_type = typename async_result< - typename std::decay::type, - Signature>::completion_handler_type; - - /** Constructor - - The constructor creates the concrete completion handler and - makes the link between the handler and the asynchronous - result. - - @param token The completion token. If this is a regular completion - handler, copies may be made as needed. If the handler is movable, - it may also be moved. - */ - explicit - async_completion(CompletionToken& token) - : completion_handler(static_cast::value, - completion_handler_type&, CompletionToken&&>::type>(token)) - , result(completion_handler) - { - // CompletionToken is not invokable with the given signature - static_assert(is_completion_handler< - completion_handler_type, Signature>::value, - "CompletionToken requirements not met: signature mismatch"); - } - - /// The final completion handler, callable with the specified signature. - typename std::conditional::value, - completion_handler_type&, - completion_handler_type - >::type completion_handler; - - /// The return value of the asynchronous initiation function. - async_result::type, Signature> result; -}; - -template -using handler_type = typename beast::async_result< - typename std::decay::type, - Signature>::completion_handler_type; - -template -using async_return_type = typename beast::async_result< - typename std::decay::type, - Signature>::return_type; - -} // beast -} // boost - -#endif diff --git a/include/boost/beast/core/bind_handler.hpp b/include/boost/beast/core/bind_handler.hpp index da3e05d1..0756bc5a 100644 --- a/include/boost/beast/core/bind_handler.hpp +++ b/include/boost/beast/core/bind_handler.hpp @@ -27,12 +27,12 @@ namespace beast { placeholders present in the list of bound arguments. Parameters which are not matched to placeholders are silently discarded. The passed handler and arguments are forwarded into the returned - handler, which provides the same `io_service` execution guarantees + handler, which provides the same `io_context` execution guarantees as the original handler. - Unlike `boost::asio::io_service::wrap`, the returned handler can - be used in a subsequent call to `boost::asio::io_service::post` - instead of `boost::asio::io_service::dispatch`, to ensure that + Unlike `boost::asio::io_context::wrap`, the returned handler can + be used in a subsequent call to `boost::asio::io_context::post` + instead of `boost::asio::io_context::dispatch`, to ensure that the handler will not be invoked immediately by the calling function. @@ -43,7 +43,8 @@ namespace beast { void signal_aborted(AsyncReadStream& stream, ReadHandler&& handler) { - stream.get_io_service().post( + boost::asio::post( + stream.get_executor(), bind_handler(std::forward(handler), boost::asio::error::operation_aborted, 0)); } diff --git a/include/boost/beast/core/buffered_read_stream.hpp b/include/boost/beast/core/buffered_read_stream.hpp index 1c15720a..378ae232 100644 --- a/include/boost/beast/core/buffered_read_stream.hpp +++ b/include/boost/beast/core/buffered_read_stream.hpp @@ -11,12 +11,12 @@ #define BOOST_BEAST_BUFFERED_READ_STREAM_HPP #include -#include #include #include #include +#include #include -#include +#include #include #include @@ -91,7 +91,8 @@ namespace beast { template class buffered_read_stream { - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); template @@ -163,11 +164,29 @@ public: return next_layer_.lowest_layer(); } - /// Get the io_service associated with the object. - boost::asio::io_service& - get_io_service() + /** Get the executor associated with the object. + + This function may be used to obtain the executor object that the stream + uses to dispatch handlers for asynchronous operations. + + @return A copy of the executor that stream will use to dispatch handlers. + + @note This function participates in overload resolution only if + `NextLayer` has a member function named `get_executor`. + */ +#if BOOST_BEAST_DOXYGEN + implementation_defined +#else + template< + class T = next_layer_type, + class = typename std::enable_if< + has_get_executor::value>::type> + auto +#endif + get_executor() noexcept -> + decltype(std::declval().get_executor()) { - return next_layer_.get_io_service(); + return next_layer_.get_executor(); } /** Access the internal buffer. @@ -265,14 +284,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code)) async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler); @@ -340,14 +356,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code)) async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler); }; diff --git a/include/boost/beast/core/buffers_adapter.hpp b/include/boost/beast/core/buffers_adapter.hpp index bf401aee..826183ed 100644 --- a/include/boost/beast/core/buffers_adapter.hpp +++ b/include/boost/beast/core/buffers_adapter.hpp @@ -35,10 +35,12 @@ namespace beast { template class buffers_adapter { - static_assert(is_mutable_buffer_sequence::value, + static_assert(boost::asio::is_mutable_buffer_sequence::value, "MutableBufferSequence requirements not met"); - using iter_type = typename MutableBufferSequence::const_iterator; + using iter_type = typename + detail::buffer_sequence_iterator< + MutableBufferSequence>::type; MutableBufferSequence bs_; iter_type begin_; diff --git a/include/boost/beast/core/buffers_prefix.hpp b/include/boost/beast/core/buffers_prefix.hpp index fcbfa59c..67d58b5c 100644 --- a/include/boost/beast/core/buffers_prefix.hpp +++ b/include/boost/beast/core/buffers_prefix.hpp @@ -34,8 +34,8 @@ class buffers_prefix_view using buffers_type = typename std::decay::type; - using iter_type = - typename buffers_type::const_iterator; + using iter_type = typename + detail::buffer_sequence_iterator::type; BufferSequence bs_; std::size_t size_; @@ -141,10 +141,8 @@ boost::asio::const_buffer buffers_prefix(std::size_t size, boost::asio::const_buffer buffer) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return { buffer_cast(buffer), - (std::min)(size, buffer_size(buffer)) }; + return {buffer.data(), + (std::min)(size, buffer.size())}; } /** Returns a prefix of a mutable buffer. @@ -166,10 +164,8 @@ boost::asio::mutable_buffer buffers_prefix(std::size_t size, boost::asio::mutable_buffer buffer) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return {buffer_cast(buffer), - (std::min)(size, buffer_size(buffer))}; + return {buffer.data(), + (std::min)(size, buffer.size())}; } /** Returns a prefix of a buffer sequence. @@ -203,8 +199,8 @@ typename std::enable_if< buffers_prefix(std::size_t size, BufferSequence const& buffers) { static_assert( - is_const_buffer_sequence::value || - is_mutable_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value || + boost::asio::is_mutable_buffer_sequence::value, "BufferSequence requirements not met"); return buffers_prefix_view(size, buffers); } @@ -221,13 +217,14 @@ buffers_prefix(std::size_t size, BufferSequence const& buffers) */ template typename std::conditional< - is_mutable_buffer_sequence::value, + boost::asio::is_mutable_buffer_sequence::value, boost::asio::mutable_buffer, boost::asio::const_buffer>::type buffers_front(BufferSequence const& buffers) { - auto const first = buffers.begin(); - if(first == buffers.end()) + auto const first = + boost::asio::buffer_sequence_begin(buffers); + if(first == boost::asio::buffer_sequence_end(buffers)) return {}; return *first; } diff --git a/include/boost/beast/core/buffers_suffix.hpp b/include/boost/beast/core/buffers_suffix.hpp index 9be31a87..81eb5a6b 100644 --- a/include/boost/beast/core/buffers_suffix.hpp +++ b/include/boost/beast/core/buffers_suffix.hpp @@ -12,11 +12,11 @@ #include #include +#include #include #include #include #include -#include #include namespace boost { @@ -57,8 +57,8 @@ class buffers_suffix using buffers_type = typename std::decay::type; - using iter_type = - typename buffers_type::const_iterator; + using iter_type = typename + detail::buffer_sequence_iterator::type; BufferSequence bs_; iter_type begin_; @@ -67,7 +67,9 @@ class buffers_suffix template buffers_suffix(Deduced&& other, std::size_t dist) : bs_(std::forward(other).bs_) - , begin_(std::next(bs_.begin(), dist)) + , begin_(std::next( + boost::asio::buffer_sequence_begin(bs_), + dist)) , skip_(other.skip_) { } diff --git a/include/boost/beast/core/buffers_to_string.hpp b/include/boost/beast/core/buffers_to_string.hpp index 79d25975..aae3d3aa 100644 --- a/include/boost/beast/core/buffers_to_string.hpp +++ b/include/boost/beast/core/buffers_to_string.hpp @@ -11,6 +11,7 @@ #define BOOST_BEAST_BUFFERS_TO_STRING_HPP #include +#include #include #include @@ -45,10 +46,10 @@ buffers_to_string(ConstBufferSequence const& buffers) { std::string result; result.reserve(boost::asio::buffer_size(buffers)); - for(boost::asio::const_buffer buffer : buffers) - result.append( - boost::asio::buffer_cast(buffer), - boost::asio::buffer_size(buffer)); + for(boost::asio::const_buffer buffer : + detail::buffers_range(buffers)) + result.append(reinterpret_cast< + char const*>(buffer.data()), buffer.size()); return result; } diff --git a/include/boost/beast/core/detail/bind_handler.hpp b/include/boost/beast/core/detail/bind_handler.hpp index 5a2ceafe..5a9059b8 100644 --- a/include/boost/beast/core/detail/bind_handler.hpp +++ b/include/boost/beast/core/detail/bind_handler.hpp @@ -11,9 +11,9 @@ #define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP #include -#include +#include +#include #include -#include #include #include #include @@ -24,13 +24,17 @@ namespace detail { /* Nullary handler that calls Handler with bound arguments. - The bound handler provides the same io_service execution + The bound handler provides the same io_context execution guarantees as the original handler. */ template class bound_handler { -private: + // Can't friend partial specializations, + // so we just friend the whole thing. + template + friend struct boost::asio::associated_executor; + using args_type = std::tuple< typename std::decay::type...>; @@ -101,6 +105,9 @@ private: public: using result_type = void; + using allocator_type = + boost::asio::associated_allocator_t; + bound_handler(bound_handler&&) = default; bound_handler(bound_handler const&) = default; @@ -113,6 +120,20 @@ public: { } + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + friend + bool + asio_handler_is_continuation(bound_handler* h) + { + using boost::asio::asio_handler_is_continuation; + return asio_handler_is_continuation(std::addressof(h->h_)); + } + template void operator()(Values&&... values) @@ -132,48 +153,30 @@ public: std::forward(values)...), index_sequence_for()); } - - friend - void* - asio_handler_allocate( - std::size_t size, bound_handler* h) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(h->h_)); - } - - friend - void - asio_handler_deallocate( - void* p, std::size_t size, bound_handler* h) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(h->h_)); - } - - friend - bool - asio_handler_is_continuation(bound_handler* h) - { - using boost::asio::asio_handler_is_continuation; - return asio_handler_is_continuation(std::addressof(h->h_)); - } - - template - friend - void - asio_handler_invoke(F&& f, bound_handler* h) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(h->h_)); - } }; } // detail } // beast + +namespace asio { +template +struct associated_executor< + beast::detail::bound_handler, Executor> +{ + using type = typename + associated_executor::type; + + static + type + get(beast::detail::bound_handler const& h, + Executor const& ex = Executor()) noexcept + { + return associated_executor< + Handler, Executor>::get(h.h_, ex); + } +}; +} // asio + } // boost namespace std { diff --git a/include/boost/beast/core/detail/buffers_ref.hpp b/include/boost/beast/core/detail/buffers_ref.hpp index e6a63622..e56a9764 100644 --- a/include/boost/beast/core/detail/buffers_ref.hpp +++ b/include/boost/beast/core/detail/buffers_ref.hpp @@ -11,6 +11,7 @@ #define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP #include +#include namespace boost { namespace beast { @@ -23,11 +24,11 @@ class buffers_ref BufferSequence const* buffers_; public: - using value_type = - typename BufferSequence::value_type; + using const_iterator = typename + buffer_sequence_iterator::type; - using const_iterator = - typename BufferSequence::const_iterator; + using value_type = typename std::iterator_traits< + const_iterator>::value_type; buffers_ref(buffers_ref const&) = default; buffers_ref& operator=(buffers_ref const&) = default; @@ -41,13 +42,13 @@ public: const_iterator begin() const { - return buffers_->begin(); + return boost::asio::buffer_sequence_begin(*buffers_); } const_iterator end() const { - return buffers_->end(); + return boost::asio::buffer_sequence_end(*buffers_); } }; diff --git a/include/boost/beast/core/detail/ostream.hpp b/include/boost/beast/core/detail/ostream.hpp index 4128d1b2..8d6eb94f 100644 --- a/include/boost/beast/core/detail/ostream.hpp +++ b/include/boost/beast/core/detail/ostream.hpp @@ -10,8 +10,10 @@ #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP #define BOOST_BEAST_DETAIL_OSTREAM_HPP -#include +#include #include +#include +#include #include #include #include @@ -46,11 +48,10 @@ std::ostream& operator<<(std::ostream& os, buffers_helper const& v) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - for(boost::asio::const_buffer b : v.b_) - os.write(buffer_cast(b), - buffer_size(b)); + for(auto b : buffers_range(v.b_)) + os.write( + reinterpret_cast(b.data()), + b.size()); return os; } @@ -130,14 +131,12 @@ private: void prepare() { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - auto mbs = buf_.prepare( + auto bs = buf_.prepare( read_size_or_throw(buf_, max_size)); - auto const mb = *mbs.begin(); - auto const p = buffer_cast(mb); + auto const b = buffers_front(bs); + auto const p = reinterpret_cast(b.data()); this->setp(p, - p + buffer_size(mb) / sizeof(CharT) - 1); + p + b.size() / sizeof(CharT) - 1); } void @@ -211,14 +210,12 @@ private: void prepare() { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - auto mbs = buf_.prepare( + auto bs = buf_.prepare( read_size_or_throw(buf_, max_size)); - auto const mb = *mbs.begin(); - auto const p = buffer_cast(mb); + auto const b = buffers_front(bs); + auto const p = reinterpret_cast(b.data()); this->setp(p, - p + buffer_size(mb) / sizeof(CharT) - 1); + p + b.size() / sizeof(CharT) - 1); } void diff --git a/include/boost/beast/core/detail/type_traits.hpp b/include/boost/beast/core/detail/type_traits.hpp index 8401fa74..06fbda29 100644 --- a/include/boost/beast/core/detail/type_traits.hpp +++ b/include/boost/beast/core/detail/type_traits.hpp @@ -12,38 +12,12 @@ #include #include -#include #include #include #include #include #include -// A few workarounds to keep things working - -namespace boost { -namespace asio { - -// for has_get_io_service -class io_service; - -// for is_dynamic_buffer -template -class basic_streambuf; - -namespace detail { - -// for is_buffer_sequence -template -class consuming_buffers; - -} // detail - -} // asio -} // boost - -//------------------------------------------------------------------------------ - namespace boost { namespace beast { namespace detail { @@ -281,57 +255,17 @@ using ConstBufferSequence = using MutableBufferSequence = BufferSequence; -template -struct is_buffer_sequence : std::false_type {}; - -template -struct is_buffer_sequence(), - std::declval() = - std::declval().begin(), - std::declval() = - std::declval().end(), - (void)0)>> : std::integral_constant::value && -#if 0 - std::is_base_of::iterator_category>::value -#else - // workaround: - // boost::asio::detail::consuming_buffers::const_iterator - // is not bidirectional - std::is_base_of::iterator_category>::value -#endif - > -{ -}; - -#if 0 -// workaround: -// boost::asio::detail::consuming_buffers::const_iterator -// is not bidirectional -template -struct is_buffer_sequence< - boost::asio::detail::consuming_buffers> - : std::true_type -{ -}; -#endif - template struct is_all_const_buffer_sequence : std::integral_constant::value && + boost::asio::is_const_buffer_sequence::value && is_all_const_buffer_sequence::value> { }; -template -struct is_all_const_buffer_sequence - : is_buffer_sequence +template +struct is_all_const_buffer_sequence + : boost::asio::is_const_buffer_sequence { }; @@ -346,6 +280,14 @@ struct common_buffers_type boost::asio::const_buffer>::type; }; +template +struct buffer_sequence_iterator +{ + using type = decltype( + boost::asio::buffer_sequence_begin( + std::declval())); +}; + // Types that meet the requirements, // for use with std::declval only. struct StreamHandler @@ -356,6 +298,54 @@ struct StreamHandler using ReadHandler = StreamHandler; using WriteHandler = StreamHandler; +template +class buffers_range_adapter +{ + Buffers const& b_; + +public: + using value_type = typename std::conditional< + std::is_convertible::type>::value_type, + boost::asio::const_buffer>::value, + boost::asio::const_buffer, + boost::asio::mutable_buffer>::type; + + /* VFALCO This isn't right, because range-for will pick up the iterator's + value_type which might not be const_buffer or mutable_buffer. We + need to declare our own iterator wrapper that converts the underlying + iterator's value_type to const_buffer or mutable_buffer so that + range-for sees one of those types. + */ + using const_iterator = typename + buffer_sequence_iterator::type; + + explicit + buffers_range_adapter(Buffers const& b) + : b_(b) + { + } + + const_iterator + begin() const noexcept + { + return boost::asio::buffer_sequence_begin(b_); + } + + const_iterator + end() const noexcept + { + return boost::asio::buffer_sequence_end(b_); + } +}; + +template +buffers_range_adapter +buffers_range(Buffers const& buffers) +{ + return buffers_range_adapter{buffers}; +} + } // detail } // beast } // boost diff --git a/include/boost/beast/core/flat_buffer.hpp b/include/boost/beast/core/flat_buffer.hpp index 2fe2b2be..0ccd16bc 100644 --- a/include/boost/beast/core/flat_buffer.hpp +++ b/include/boost/beast/core/flat_buffer.hpp @@ -84,10 +84,10 @@ public: using allocator_type = Allocator; /// The type used to represent the input sequence as a list of buffers. - using const_buffers_type = boost::asio::mutable_buffers_1; + using const_buffers_type = boost::asio::mutable_buffer; /// The type used to represent the output sequence as a list of buffers. - using mutable_buffers_type = boost::asio::mutable_buffers_1; + using mutable_buffers_type = boost::asio::mutable_buffer; /// Destructor ~basic_flat_buffer(); diff --git a/include/boost/beast/core/flat_static_buffer.hpp b/include/boost/beast/core/flat_static_buffer.hpp index 8007011f..cfac9855 100644 --- a/include/boost/beast/core/flat_static_buffer.hpp +++ b/include/boost/beast/core/flat_static_buffer.hpp @@ -52,13 +52,13 @@ public: This buffer sequence is guaranteed to have length 1. */ - using const_buffers_type = boost::asio::mutable_buffers_1; + using const_buffers_type = boost::asio::mutable_buffer; /** The type used to represent the output sequence as a list of buffers. This buffer sequence is guaranteed to have length 1. */ - using mutable_buffers_type = boost::asio::mutable_buffers_1; + using mutable_buffers_type = boost::asio::mutable_buffer; /** Constructor diff --git a/include/boost/beast/core/handler_alloc.hpp b/include/boost/beast/core/handler_alloc.hpp deleted file mode 100644 index 896e88a4..00000000 --- a/include/boost/beast/core/handler_alloc.hpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_HANDLER_ALLOC_HPP -#define BOOST_BEAST_HANDLER_ALLOC_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { - -// Guidance from -// http://howardhinnant.github.io/allocator_boilerplate.html - -/** An allocator that uses handler customizations. - - This allocator uses the handler customizations `asio_handler_allocate` - and `asio_handler_deallocate` to manage memory. It meets the requirements - of @b Allocator and can be used anywhere a `std::allocator` is - accepted. - - @tparam T The type of objects allocated by the allocator. - - @tparam Handler The type of handler. - - @note Memory allocated by this allocator must be freed before - the handler is invoked or undefined behavior results. This behavior - is described as the "deallocate before invocation" Asio guarantee. -*/ -#if BOOST_BEAST_DOXYGEN -template -class handler_alloc; -#else -template -class handler_alloc -{ -private: - // We want a partial template specialization as a friend - // but that isn't allowed so we friend all versions. This - // should produce a compile error if Handler is not - // constructible from H. - // - template - friend class handler_alloc; - - Handler& h_; - -public: - using value_type = T; - using is_always_equal = std::true_type; - using pointer = T*; - using reference = T&; - using const_pointer = T const*; - using const_reference = T const&; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - template - struct rebind - { - using other = handler_alloc; - }; - - handler_alloc() = delete; - handler_alloc(handler_alloc&&) = default; - handler_alloc(handler_alloc const&) = default; - handler_alloc& operator=(handler_alloc&&) = default; - handler_alloc& operator=(handler_alloc const&) = default; - - /** Construct the allocator. - - A reference of the handler is stored. The handler must - remain valid for at least the lifetime of the allocator. - */ - explicit - handler_alloc(Handler& h) - : h_(h) - { - } - - /// Copy constructor - template - handler_alloc( - handler_alloc const& other) - : h_(other.h_) - { - } - - value_type* - allocate(size_type n) - { - auto const size = n * sizeof(T); - using boost::asio::asio_handler_allocate; - return static_cast( - asio_handler_allocate(size, std::addressof(h_))); - } - - void - deallocate(value_type* p, size_type n) - { - auto const size = n * sizeof(T); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(p, size, std::addressof(h_)); - } - -//#if BOOST_WORKAROUND(BOOST_GCC, < 60000) // Works, but too coarse - -#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000 - template - void - construct(U* ptr, Args&&... args) - { - ::new((void*)ptr) U(std::forward(args)...); - } - - template - void - destroy(U* ptr) - { - ptr->~U(); - } -#endif - - template - friend - bool - operator==( - handler_alloc const&, - handler_alloc const&) - { - return true; - } - - template - friend - bool - operator!=( - handler_alloc const& lhs, - handler_alloc const& rhs) - { - return ! (lhs == rhs); - } -}; -#endif - -} // beast -} // boost - -#endif diff --git a/include/boost/beast/core/impl/buffered_read_stream.ipp b/include/boost/beast/core/impl/buffered_read_stream.ipp index 020a16c0..f88c2748 100644 --- a/include/boost/beast/core/impl/buffered_read_stream.ipp +++ b/include/boost/beast/core/impl/buffered_read_stream.ipp @@ -16,9 +16,10 @@ #include #include #include -#include +#include +#include #include -#include +#include #include namespace boost { @@ -48,28 +49,28 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()(error_code const& ec, std::size_t bytes_transferred); - friend - void* asio_handler_allocate( - std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(read_some_op* op) { @@ -77,14 +78,6 @@ public: return asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, read_some_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke(f, std::addressof(op->h_)); - } }; template @@ -116,9 +109,9 @@ read_some_op::operator()( } step_ = 3; - s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); - return; case 1: // upcall @@ -153,11 +146,11 @@ auto buffered_read_stream:: async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler) -> - async_return_type + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(error_code)) { static_assert(is_async_write_stream::value, "AsyncWriteStream requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); static_assert(is_completion_handler::value, "SyncReadStream requirements not met"); - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); error_code ec; @@ -195,7 +188,7 @@ read_some(MutableBufferSequence const& buffers, { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); using boost::asio::buffer_size; @@ -226,20 +219,20 @@ auto buffered_read_stream:: async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler) -> - async_return_type + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(error_code)) { static_assert(is_async_read_stream::value, - "Stream requirements not met"); - static_assert(is_mutable_buffer_sequence< + "AsyncReadStream requirements not met"); + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); if(buffer_.size() == 0 && capacity_ == 0) return next_layer_.async_read_some(buffers, std::forward(handler)); - async_completion init{handler}; - read_some_op>{ + read_some_op{ init.completion_handler, *this, buffers}( error_code{}, 0); return init.result.get(); diff --git a/include/boost/beast/core/impl/buffers_adapter.ipp b/include/boost/beast/core/impl/buffers_adapter.ipp index d88d6734..e16d2a9b 100644 --- a/include/boost/beast/core/impl/buffers_adapter.ipp +++ b/include/boost/beast/core/impl/buffers_adapter.ipp @@ -90,11 +90,10 @@ public: reference operator*() const { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return value_type{buffer_cast(*it_), - (ba_->out_ == ba_->bs_.end() || - it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} + + value_type const b = *it_; + return value_type{b.data(), + (ba_->out_ == boost::asio::buffer_sequence_end(ba_->bs_) || + it_ != ba_->out_) ? b.size() : ba_->out_pos_} + (it_ == ba_->begin_ ? ba_->in_pos_ : 0); } @@ -233,11 +232,10 @@ public: reference operator*() const { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return value_type{buffer_cast(*it_), + value_type const b = *it_; + return value_type{b.data(), it_ == std::prev(ba_->end_) ? - ba_->out_end_ : buffer_size(*it_)} + + ba_->out_end_ : b.size()} + (it_ == ba_->out_ ? ba_->out_pos_ : 0); } @@ -288,7 +286,9 @@ private: template inline auto -buffers_adapter::mutable_buffers_type::begin() const -> +buffers_adapter:: +mutable_buffers_type:: +begin() const -> const_iterator { return const_iterator{*ba_, ba_->out_}; @@ -297,7 +297,9 @@ buffers_adapter::mutable_buffers_type::begin() const -> template inline auto -buffers_adapter::mutable_buffers_type::end() const -> +buffers_adapter:: +mutable_buffers_type:: +end() const -> const_iterator { return const_iterator{*ba_, ba_->end_}; @@ -309,9 +311,9 @@ template buffers_adapter::buffers_adapter( buffers_adapter&& other) : buffers_adapter(std::move(other), - std::distance(other.bs_.begin(), other.begin_), - std::distance(other.bs_.begin(), other.out_), - std::distance(other.bs_.begin(), other.end_)) + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.begin_), + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.out_), + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.end_)) { } @@ -319,9 +321,9 @@ template buffers_adapter::buffers_adapter( buffers_adapter const& other) : buffers_adapter(other, - std::distance(other.bs_.begin(), other.begin_), - std::distance(other.bs_.begin(), other.out_), - std::distance(other.bs_.begin(), other.end_)) + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.begin_), + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.out_), + std::distance(boost::asio::buffer_sequence_begin(other.bs_), other.end_)) { } @@ -331,15 +333,18 @@ buffers_adapter::operator=( buffers_adapter&& other) -> buffers_adapter& { auto const nbegin = std::distance( - other.bs_.begin(), other.begin_); + boost::asio::buffer_sequence_begin(other.bs_), + other.begin_); auto const nout = std::distance( - other.bs_.begin(), other.out_); + boost::asio::buffer_sequence_begin(other.bs_), + other.out_); auto const nend = std::distance( - other.bs_.begin(), other.end_); + boost::asio::buffer_sequence_begin(other.bs_), + other.end_); bs_ = std::move(other.bs_); - begin_ = std::next(bs_.begin(), nbegin); - out_ = std::next(bs_.begin(), nout); - end_ = std::next(bs_.begin(), nend); + begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin); + out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout); + end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend); max_size_ = other.max_size_; in_pos_ = other.in_pos_; in_size_ = other.in_size_; @@ -354,15 +359,18 @@ buffers_adapter::operator=( buffers_adapter const& other) -> buffers_adapter& { auto const nbegin = std::distance( - other.bs_.begin(), other.begin_); + boost::asio::buffer_sequence_begin(other.bs_), + other.begin_); auto const nout = std::distance( - other.bs_.begin(), other.out_); + boost::asio::buffer_sequence_begin(other.bs_), + other.out_); auto const nend = std::distance( - other.bs_.begin(), other.end_); + boost::asio::buffer_sequence_begin(other.bs_), + other.end_); bs_ = other.bs_; - begin_ = std::next(bs_.begin(), nbegin); - out_ = std::next(bs_.begin(), nout); - end_ = std::next(bs_.begin(), nend); + begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin); + out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout); + end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend); max_size_ = other.max_size_; in_pos_ = other.in_pos_; in_size_ = other.in_size_; @@ -375,9 +383,9 @@ template buffers_adapter::buffers_adapter( MutableBufferSequence const& bs) : bs_(bs) - , begin_(bs_.begin()) - , out_(bs_.begin()) - , end_(bs_.begin()) + , begin_(boost::asio::buffer_sequence_begin(bs_)) + , out_ (boost::asio::buffer_sequence_begin(bs_)) + , end_ (boost::asio::buffer_sequence_begin(bs_)) , max_size_(boost::asio::buffer_size(bs_)) { } @@ -389,13 +397,14 @@ buffers_adapter::prepare(std::size_t n) -> { using boost::asio::buffer_size; end_ = out_; - if(end_ != bs_.end()) + if(end_ != boost::asio::buffer_sequence_end(bs_)) { auto size = buffer_size(*end_) - out_pos_; if(n > size) { n -= size; - while(++end_ != bs_.end()) + while(++end_ != + boost::asio::buffer_sequence_end(bs_)) { size = buffer_size(*end_); if(n < size) diff --git a/include/boost/beast/core/impl/buffers_cat.ipp b/include/boost/beast/core/impl/buffers_cat.ipp index bed9606a..d92d5523 100644 --- a/include/boost/beast/core/impl/buffers_cat.ipp +++ b/include/boost/beast/core/impl/buffers_cat.ipp @@ -30,7 +30,7 @@ class buffers_cat_view::const_iterator std::size_t n_; std::tuple const* bn_; std::array()> buf_; + typename detail::buffer_sequence_iterator::type...>()> buf_; friend class buffers_cat_view; @@ -38,8 +38,8 @@ class buffers_cat_view::const_iterator using C = std::integral_constant; template - using iter_t = typename std::tuple_element< - I, std::tuple>::type::const_iterator; + using iter_t = typename detail::buffer_sequence_iterator< + typename std::tuple_element>::type>::type; template iter_t& @@ -123,7 +123,8 @@ private: { n_ = I; new(&buf_[0]) iter_t{ - std::get(*bn_).begin()}; + boost::asio::buffer_sequence_begin( + std::get(*bn_))}; return; } construct(C{}); @@ -138,7 +139,8 @@ private: { n_ = I; new(&buf_[0]) iter_t{ - std::get(*bn_).end()}; + boost::asio::buffer_sequence_end( + std::get(*bn_))}; return; } BOOST_THROW_EXCEPTION(std::logic_error{ @@ -154,7 +156,8 @@ private: { n_ = I; new(&buf_[0]) iter_t{ - std::get(*bn_).end()}; + boost::asio::buffer_sequence_end( + std::get(*bn_))}; return; } rconstruct(C{}); @@ -268,7 +271,8 @@ private: if(n_ == I) { if(++iter() != - std::get(*bn_).end()) + boost::asio::buffer_sequence_end( + std::get(*bn_))) return; using Iter = iter_t; iter().~Iter(); @@ -292,7 +296,9 @@ private: { if(n_ == I) { - if(iter() != std::get(*bn_).begin()) + if(iter() != + boost::asio::buffer_sequence_begin( + std::get(*bn_))) { --iter(); return; @@ -309,7 +315,9 @@ private: decrement(C<0> const&) { auto constexpr I = 0; - if(iter() != std::get(*bn_).begin()) + if(iter() != + boost::asio::buffer_sequence_begin( + std::get(*bn_))) { --iter(); return; diff --git a/include/boost/beast/core/impl/buffers_prefix.ipp b/include/boost/beast/core/impl/buffers_prefix.ipp index f40f7f56..0bb92cc3 100644 --- a/include/boost/beast/core/impl/buffers_prefix.ipp +++ b/include/boost/beast/core/impl/buffers_prefix.ipp @@ -27,10 +27,8 @@ boost::asio::const_buffer buffers_prefix(std::size_t size, boost::asio::const_buffer buffer) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return {buffer_cast(buffer), - (std::min)(size, buffer_size(buffer))}; + return {buffer.data(), + (std::min)(size, buffer.size())}; } inline @@ -38,10 +36,8 @@ boost::asio::mutable_buffer buffers_prefix(std::size_t size, boost::asio::mutable_buffer buffer) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return {buffer_cast(buffer), - (std::min)(size, buffer_size(buffer))}; + return {buffer.data(), + (std::min)(size, buffer.size())}; } } // detail @@ -138,7 +134,7 @@ private: std::false_type) : b_(&b) , remain_(b_->size_) - , it_(b_->bs_.begin()) + , it_(boost::asio::buffer_sequence_begin(b_->bs_)) { } }; @@ -149,7 +145,7 @@ buffers_prefix_view:: setup(std::size_t size) { size_ = 0; - end_ = bs_.begin(); + end_ = boost::asio::buffer_sequence_begin(bs_); auto const last = bs_.end(); while(end_ != last) { @@ -170,7 +166,8 @@ buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view&& other) : buffers_prefix_view(std::move(other), std::distance( - other.bs_.begin(), other.end_)) + boost::asio::buffer_sequence_begin(other.bs_), + other.end_)) { } @@ -179,7 +176,8 @@ buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view const& other) : buffers_prefix_view(other, std::distance( - other.bs_.begin(), other.end_)) + boost::asio::buffer_sequence_begin(other.bs_), + other.end_)) { } @@ -190,10 +188,13 @@ operator=(buffers_prefix_view&& other) -> buffers_prefix_view& { auto const dist = std::distance( - other.bs_.begin(), other.end_); + boost::asio::buffer_sequence_begin(other.bs_), + other.end_); bs_ = std::move(other.bs_); size_ = other.size_; - end_ = std::next(bs_.begin(), dist); + end_ = std::next( + boost::asio::buffer_sequence_begin(bs_), + dist); return *this; } @@ -204,10 +205,13 @@ operator=(buffers_prefix_view const& other) -> buffers_prefix_view& { auto const dist = std::distance( - other.bs_.begin(), other.end_); + boost::asio::buffer_sequence_begin(other.bs_), + other.end_); bs_ = other.bs_; size_ = other.size_; - end_ = std::next(bs_.begin(), dist); + end_ = std::next( + boost::asio::buffer_sequence_begin(bs_), + dist); return *this; } diff --git a/include/boost/beast/core/impl/buffers_suffix.ipp b/include/boost/beast/core/impl/buffers_suffix.ipp index f46e79ae..6356d63e 100644 --- a/include/boost/beast/core/impl/buffers_suffix.ipp +++ b/include/boost/beast/core/impl/buffers_suffix.ipp @@ -25,8 +25,8 @@ class buffers_suffix::const_iterator { friend class buffers_suffix; - using iter_type = - typename Buffers::const_iterator; + using iter_type = typename + detail::buffer_sequence_iterator::type; iter_type it_; buffers_suffix const* b_ = nullptr; @@ -117,7 +117,7 @@ private: template buffers_suffix:: buffers_suffix() - : begin_(bs_.begin()) + : begin_(boost::asio::buffer_sequence_begin(bs_)) { } @@ -126,7 +126,8 @@ buffers_suffix:: buffers_suffix(buffers_suffix&& other) : buffers_suffix(std::move(other), std::distance( - other.bs_.begin(), other.begin_)) + boost::asio::buffer_sequence_begin( + other.bs_), other.begin_)) { } @@ -135,7 +136,8 @@ buffers_suffix:: buffers_suffix(buffers_suffix const& other) : buffers_suffix(other, std::distance( - other.bs_.begin(), other.begin_)) + boost::asio::buffer_sequence_begin( + other.bs_), other.begin_)) { } @@ -143,11 +145,11 @@ template buffers_suffix:: buffers_suffix(Buffers const& bs) : bs_(bs) - , begin_(bs_.begin()) + , begin_(boost::asio::buffer_sequence_begin(bs_)) { static_assert( - is_const_buffer_sequence::value|| - is_mutable_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value|| + boost::asio::is_mutable_buffer_sequence::value, "BufferSequence requirements not met"); } @@ -156,7 +158,7 @@ template buffers_suffix:: buffers_suffix(boost::in_place_init_t, Args&&... args) : bs_(std::forward(args)...) - , begin_(bs_.begin()) + , begin_(boost::asio::buffer_sequence_begin(bs_)) { static_assert(sizeof...(Args) > 0, "Missing constructor arguments"); @@ -172,9 +174,12 @@ operator=(buffers_suffix&& other) -> buffers_suffix& { auto const dist = std::distance( - other.bs_.begin(), other.begin_); + boost::asio::buffer_sequence_begin(other.bs_), + other.begin_); bs_ = std::move(other.bs_); - begin_ = std::next(bs_.begin(), dist); + begin_ = std::next( + boost::asio::buffer_sequence_begin(bs_), + dist); skip_ = other.skip_; return *this; } @@ -186,9 +191,11 @@ operator=(buffers_suffix const& other) -> buffers_suffix& { auto const dist = std::distance( - other.bs_.begin(), other.begin_); + boost::asio::buffer_sequence_begin(other.bs_), + other.begin_); bs_ = other.bs_; - begin_ = std::next(bs_.begin(), dist); + begin_ = std::next( + boost::asio::buffer_sequence_begin(bs_), dist); skip_ = other.skip_; return *this; } @@ -210,7 +217,8 @@ buffers_suffix:: end() const -> const_iterator { - return const_iterator{*this, bs_.end()}; + return const_iterator{*this, + boost::asio::buffer_sequence_end(bs_)}; } template @@ -219,7 +227,9 @@ buffers_suffix:: consume(std::size_t amount) { using boost::asio::buffer_size; - for(;amount > 0 && begin_ != bs_.end(); ++begin_) + auto const end = + boost::asio::buffer_sequence_end(bs_); + for(;amount > 0 && begin_ != end; ++begin_) { auto const len = buffer_size(*begin_) - skip_; diff --git a/include/boost/beast/core/impl/handler_ptr.ipp b/include/boost/beast/core/impl/handler_ptr.ipp index aab5d8ce..15a159a8 100644 --- a/include/boost/beast/core/impl/handler_ptr.ipp +++ b/include/boost/beast/core/impl/handler_ptr.ipp @@ -10,9 +10,7 @@ #ifndef BOOST_BEAST_IMPL_HANDLER_PTR_HPP #define BOOST_BEAST_IMPL_HANDLER_PTR_HPP -#include -#include -#include +#include #include #include @@ -27,10 +25,11 @@ P(DeducedHandler&& h, Args&&... args) : n(1) , handler(std::forward(h)) { - using boost::asio::asio_handler_allocate; - t = reinterpret_cast( - asio_handler_allocate( - sizeof(T), std::addressof(handler))); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator(handler)}; + t = std::allocator_traits::allocate(alloc, 1); try { t = new(t) T{handler, @@ -38,9 +37,8 @@ P(DeducedHandler&& h, Args&&... args) } catch(...) { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - t, sizeof(T), std::addressof(handler)); + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, t, 1); throw; } } @@ -56,9 +54,13 @@ handler_ptr:: if(p_->t) { p_->t->~T(); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p_->t, sizeof(T), std::addressof(p_->handler)); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator( + p_->handler)}; + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, p_->t, 1); } delete p_; } @@ -108,9 +110,13 @@ release_handler() -> BOOST_ASSERT(p_); BOOST_ASSERT(p_->t); p_->t->~T(); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p_->t, sizeof(T), std::addressof(p_->handler)); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator( + p_->handler)}; + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, p_->t, 1); p_->t = nullptr; return std::move(p_->handler); } @@ -124,9 +130,13 @@ invoke(Args&&... args) BOOST_ASSERT(p_); BOOST_ASSERT(p_->t); p_->t->~T(); - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p_->t, sizeof(T), std::addressof(p_->handler)); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator( + p_->handler)}; + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, p_->t, 1); p_->t = nullptr; p_->handler(std::forward(args)...); } diff --git a/include/boost/beast/core/impl/read_size.ipp b/include/boost/beast/core/impl/read_size.ipp index 9e72ffed..d29eeaa7 100644 --- a/include/boost/beast/core/impl/read_size.ipp +++ b/include/boost/beast/core/impl/read_size.ipp @@ -38,7 +38,8 @@ std::size_t read_size(DynamicBuffer& buffer, std::size_t max_size, std::false_type) { - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); BOOST_ASSERT(max_size >= 1); auto const size = buffer.size(); diff --git a/include/boost/beast/core/ostream.hpp b/include/boost/beast/core/ostream.hpp index 50aca179..1f00289b 100644 --- a/include/boost/beast/core/ostream.hpp +++ b/include/boost/beast/core/ostream.hpp @@ -49,7 +49,7 @@ detail::buffers_helper #endif buffers(ConstBufferSequence const& b) { - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); return detail::buffers_helper< @@ -90,7 +90,8 @@ detail::ostream_helper< #endif ostream(DynamicBuffer& buffer) { - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); return detail::ostream_helper< DynamicBuffer, char, std::char_traits, diff --git a/include/boost/beast/core/type_traits.hpp b/include/boost/beast/core/type_traits.hpp index 269f3da6..d622e0e8 100644 --- a/include/boost/beast/core/type_traits.hpp +++ b/include/boost/beast/core/type_traits.hpp @@ -19,153 +19,6 @@ namespace boost { namespace beast { -//------------------------------------------------------------------------------ -// -// Buffer concepts -// -//------------------------------------------------------------------------------ - -/** Determine if `T` meets the requirements of @b ConstBufferSequence. - - Metafunctions are used to perform compile time checking of template - types. This type will be `std::true_type` if `T` meets the requirements, - else the type will be `std::false_type`. - - @par Example - - Use with `static_assert`: - - @code - template - void f(ConstBufferSequence const& buffers) - { - static_assert(is_const_buffer_sequence::value, - "ConstBufferSequence requirements not met"); - ... - @endcode - - Use with `std::enable_if` (SFINAE): - - @code - template - typename std::enable_if::value>::type - f(ConstBufferSequence const& buffers); - @endcode -*/ -template -#if BOOST_BEAST_DOXYGEN -struct is_const_buffer_sequence : std::integral_constant -#else -struct is_const_buffer_sequence : - detail::is_buffer_sequence -#endif -{ -}; - -/** Determine if `T` meets the requirements of @b MutableBufferSequence. - - Metafunctions are used to perform compile time checking of template - types. This type will be `std::true_type` if `T` meets the requirements, - else the type will be `std::false_type`. - - @par Example - - Use with `static_assert`: - - @code - template - void f(MutableBufferSequence const& buffers) - { - static_assert(is_const_buffer_sequence::value, - "MutableBufferSequence requirements not met"); - ... - @endcode - - Use with `std::enable_if` (SFINAE): - - @code - template - typename std::enable_if::value>::type - f(MutableBufferSequence const& buffers); - @endcode -*/ -template -#if BOOST_BEAST_DOXYGEN -struct is_mutable_buffer_sequence : std::integral_constant -#else -struct is_mutable_buffer_sequence : - detail::is_buffer_sequence -#endif -{ -}; - -/** Determine if `T` meets the requirements of @b DynamicBuffer. - - Metafunctions are used to perform compile time checking of template - types. This type will be `std::true_type` if `T` meets the requirements, - else the type will be `std::false_type`. - - @par Example - - Use with `static_assert`: - - @code - template - void f(DynamicBuffer& buffer) - { - static_assert(is_dynamic_buffer::value, - "DynamicBuffer requirements not met"); - ... - @endcode - - Use with `std::enable_if` (SFINAE): - - @code - template - typename std::enable_if::value>::type - f(DynamicBuffer const& buffer); - @endcode -*/ -#if BOOST_BEAST_DOXYGEN -template -struct is_dynamic_buffer : std::integral_constant {}; -#else -template -struct is_dynamic_buffer : std::false_type {}; - -template -struct is_dynamic_buffer() = - std::declval().size(), - std::declval() = - std::declval().max_size(), - std::declval() = - std::declval().capacity(), - std::declval().commit(std::declval()), - std::declval().consume(std::declval()), - (void)0)> > : std::integral_constant::value && - is_mutable_buffer_sequence< - typename T::mutable_buffers_type>::value && - std::is_same().data())>::value && - std::is_same().prepare( - std::declval()))>::value - > -{ -}; - -// Special case for Boost.Asio which doesn't adhere to -// net-ts but still provides a read_size_helper so things work -template -struct is_dynamic_buffer< - boost::asio::basic_streambuf> : std::true_type -{ -}; -#endif - //------------------------------------------------------------------------------ // // Handler concepts @@ -209,7 +62,7 @@ using is_completion_handler = std::integral_constant void maybe_hello(T& t, std::true_type) { - t.get_io_service().post([]{ std::cout << "Hello, world!" << std::endl; }); + boost::asio::post( + t.get_executor(), + [] + { + std::cout << "Hello, world!" << std::endl; + }); } template void maybe_hello(T&, std::false_type) { - // T does not have get_io_service + // T does not have get_executor } template void maybe_hello(T& t) { - maybe_hello(t, has_get_io_service{}); + maybe_hello(t, has_get_executor{}); } @endcode @@ -244,24 +102,23 @@ using is_completion_handler = std::integral_constant::value, - "Missing get_io_service member"); + static_assert(has_get_executor::value, "Missing get_executor member"); @endcode */ #if BOOST_BEAST_DOXYGEN template -struct has_get_io_service : std::integral_constant{}; +struct has_get_executor : std::integral_constant{}; #else template -struct has_get_io_service : std::false_type {}; +struct has_get_executor : std::false_type {}; template -struct has_get_io_service( - std::declval().get_io_service()), +struct has_get_executor().get_executor(), (void)0)>> : std::true_type {}; #endif @@ -350,7 +207,7 @@ struct is_async_read_stream(), std::declval()), (void)0)>> : std::integral_constant::value + has_get_executor::value > {}; #endif @@ -394,7 +251,7 @@ struct is_async_write_stream(), std::declval()), (void)0)>> : std::integral_constant::value + has_get_executor::value > {}; #endif @@ -439,12 +296,10 @@ struct is_sync_read_stream() = std::declval().read_some( std::declval(), std::declval()), - (void)0)>> : std::integral_constant::value - > {}; + (void)0)>> : std::true_type {}; #endif -/** Determine if `T` meets the requirements of @b SyncWriterStream. +/** Determine if `T` meets the requirements of @b SyncWriteStream. Metafunctions are used to perform compile time checking of template types. This type will be `std::true_type` if `T` meets the requirements, @@ -485,9 +340,7 @@ struct is_sync_write_stream() = std::declval().write_some( std::declval(), std::declval()), - (void)0)>> : std::integral_constant::value - > {}; + (void)0)>> : std::true_type {}; #endif /** Determine if `T` meets the requirements of @b AsyncStream. diff --git a/include/boost/beast/http/basic_dynamic_body.hpp b/include/boost/beast/http/basic_dynamic_body.hpp index fb4c92fa..6bc8fa91 100644 --- a/include/boost/beast/http/basic_dynamic_body.hpp +++ b/include/boost/beast/http/basic_dynamic_body.hpp @@ -32,7 +32,8 @@ namespace http { template struct basic_dynamic_body { - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); /** The type of container used for the body diff --git a/include/boost/beast/http/basic_file_body.hpp b/include/boost/beast/http/basic_file_body.hpp index 8767a71e..22fb91fc 100644 --- a/include/boost/beast/http/basic_file_body.hpp +++ b/include/boost/beast/http/basic_file_body.hpp @@ -143,7 +143,13 @@ public: /** Set the open file - This function is used to set the open + This function is used to set the open file. Any previously + set file will be closed. + + @param file The file to set. The file must be open or else + an error occurs + + @param ec Set to the error, if any occurred */ void reset(File&& file, error_code& ec); @@ -229,7 +235,7 @@ public: // The type of buffer sequence returned by `get`. // using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; // Constructor. // @@ -485,13 +491,13 @@ put(ConstBufferSequence const& buffers, error_code& ec) // Loop over all the buffers in the sequence, // and write each one to the file. - for(boost::asio::const_buffer buffer : buffers) + for(auto it = boost::asio::buffer_sequence_begin(buffers); + it != boost::asio::buffer_sequence_end(buffers); ++it) { // Write this buffer to the file + boost::asio::const_buffer buffer = *it; nwritten += body_.file_.write( - boost::asio::buffer_cast(buffer), - boost::asio::buffer_size(buffer), - ec); + buffer.data(), buffer.size(), ec); if(ec) return nwritten; } diff --git a/include/boost/beast/http/basic_parser.hpp b/include/boost/beast/http/basic_parser.hpp index b4b138a9..fdc002f8 100644 --- a/include/boost/beast/http/basic_parser.hpp +++ b/include/boost/beast/http/basic_parser.hpp @@ -515,7 +515,7 @@ public: #if ! BOOST_BEAST_DOXYGEN std::size_t - put(boost::asio::const_buffers_1 const& buffer, + put(boost::asio::const_buffer const& buffer, error_code& ec); #endif diff --git a/include/boost/beast/http/buffer_body.hpp b/include/boost/beast/http/buffer_body.hpp index 43032cda..82b2b4b4 100644 --- a/include/boost/beast/http/buffer_body.hpp +++ b/include/boost/beast/http/buffer_body.hpp @@ -105,7 +105,7 @@ struct buffer_body public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit diff --git a/include/boost/beast/http/chunk_encode.hpp b/include/boost/beast/http/chunk_encode.hpp index 2afc099b..4994765f 100644 --- a/include/boost/beast/http/chunk_encode.hpp +++ b/include/boost/beast/http/chunk_encode.hpp @@ -106,7 +106,7 @@ class chunk_header { using view_type = buffers_cat_view< detail::chunk_size, // chunk-size - boost::asio::const_buffers_1, // chunk-extensions + boost::asio::const_buffer, // chunk-extensions chunk_crlf>; // CRLF std::shared_ptr< @@ -285,7 +285,7 @@ class chunk_body { using view_type = buffers_cat_view< detail::chunk_size, // chunk-size - boost::asio::const_buffers_1, // chunk-extensions + boost::asio::const_buffer, // chunk-extensions chunk_crlf, // CRLF ConstBufferSequence, // chunk-body chunk_crlf>; // CRLF @@ -459,7 +459,7 @@ class chunk_last { static_assert( is_fields::value || - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, "Trailer requirements not met"); using buffers_type = typename diff --git a/include/boost/beast/http/detail/chunk_encode.hpp b/include/boost/beast/http/detail/chunk_encode.hpp index ad1c223c..f0f3c858 100644 --- a/include/boost/beast/http/detail/chunk_encode.hpp +++ b/include/boost/beast/http/detail/chunk_encode.hpp @@ -25,7 +25,7 @@ namespace detail { struct chunk_extensions { virtual ~chunk_extensions() = default; - virtual boost::asio::const_buffers_1 str() = 0; + virtual boost::asio::const_buffer str() = 0; }; template @@ -43,7 +43,7 @@ struct chunk_extensions_impl : chunk_extensions { } - boost::asio::const_buffers_1 + boost::asio::const_buffer str() override { auto const s = ext_.str(); @@ -151,7 +151,7 @@ prepare(std::size_t n) /// Returns a buffer sequence holding a CRLF for chunk encoding inline -boost::asio::const_buffers_1 +boost::asio::const_buffer chunk_crlf() { return {"\r\n", 2}; @@ -159,7 +159,7 @@ chunk_crlf() /// Returns a buffer sequence holding a final chunk header inline -boost::asio::const_buffers_1 +boost::asio::const_buffer chunk_last() { return {"0\r\n", 3}; diff --git a/include/boost/beast/http/impl/basic_parser.ipp b/include/boost/beast/http/impl/basic_parser.ipp index 73810639..2837095c 100644 --- a/include/boost/beast/http/impl/basic_parser.ipp +++ b/include/boost/beast/http/impl/basic_parser.ipp @@ -103,14 +103,13 @@ basic_parser:: put(ConstBufferSequence const& buffers, error_code& ec) { - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - using boost::asio::buffer_cast; using boost::asio::buffer_copy; using boost::asio::buffer_size; - auto const p = buffers.begin(); - auto const last = buffers.end(); + auto const p = boost::asio::buffer_sequence_begin(buffers); + auto const last = boost::asio::buffer_sequence_end(buffers); if(p == last) { ec.assign(0, ec.category()); @@ -119,10 +118,7 @@ put(ConstBufferSequence const& buffers, if(std::next(p) == last) { // single buffer - auto const b = *p; - return put(boost::asio::const_buffers_1{ - buffer_cast(b), - buffer_size(b)}, ec); + return put(boost::asio::const_buffer(*p), ec); } auto const size = buffer_size(buffers); if(size <= max_stack_buffer) @@ -136,21 +132,21 @@ put(ConstBufferSequence const& buffers, // flatten buffer_copy(boost::asio::buffer( buf_.get(), buf_len_), buffers); - return put(boost::asio::const_buffers_1{ + return put(boost::asio::const_buffer{ buf_.get(), buf_len_}, ec); } template std::size_t basic_parser:: -put(boost::asio::const_buffers_1 const& buffer, +put(boost::asio::const_buffer const& buffer, error_code& ec) { BOOST_ASSERT(state_ != state::complete); using boost::asio::buffer_size; - auto p = boost::asio::buffer_cast< - char const*>(*buffer.begin()); - auto n = buffer_size(*buffer.begin()); + auto p = reinterpret_cast< + char const*>(buffer.data()); + auto n = buffer.size(); auto const p0 = p; auto const p1 = p0 + n; ec.assign(0, ec.category()); @@ -324,7 +320,7 @@ put_from_stack(std::size_t size, using boost::asio::buffer; using boost::asio::buffer_copy; buffer_copy(buffer(buf, sizeof(buf)), buffers); - return put(boost::asio::const_buffers_1{ + return put(boost::asio::const_buffer{ buf, size}, ec); } diff --git a/include/boost/beast/http/impl/chunk_encode.ipp b/include/boost/beast/http/impl/chunk_encode.ipp index 461c895a..ddb96881 100644 --- a/include/boost/beast/http/impl/chunk_encode.ipp +++ b/include/boost/beast/http/impl/chunk_encode.ipp @@ -24,7 +24,7 @@ chunk_header:: chunk_header(std::size_t size) : view_( size, - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}) { BOOST_ASSERT(size > 0); @@ -37,7 +37,7 @@ chunk_header( string_view extensions) : view_( size, - boost::asio::const_buffers_1{ + boost::asio::const_buffer{ extensions.data(), extensions.size()}, chunk_crlf{}) { @@ -90,7 +90,7 @@ chunk_body:: chunk_body(ConstBufferSequence const& buffers) : view_( boost::asio::buffer_size(buffers), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}, buffers, chunk_crlf{}) @@ -104,7 +104,7 @@ chunk_body( string_view extensions) : view_( boost::asio::buffer_size(buffers), - boost::asio::const_buffers_1{ + boost::asio::const_buffer{ extensions.data(), extensions.size()}, chunk_crlf{}, buffers, diff --git a/include/boost/beast/http/impl/fields.ipp b/include/boost/beast/http/impl/fields.ipp index 6d78382a..64bf7f14 100644 --- a/include/boost/beast/http/impl/fields.ipp +++ b/include/boost/beast/http/impl/fields.ipp @@ -143,9 +143,9 @@ public: }; using view_type = buffers_cat_view< - boost::asio::const_buffers_1, - boost::asio::const_buffers_1, - boost::asio::const_buffers_1, + boost::asio::const_buffer, + boost::asio::const_buffer, + boost::asio::const_buffer, field_range, chunk_crlf>; @@ -178,9 +178,9 @@ reader(basic_fields const& f) : f_(f) { view_.emplace( - boost::asio::const_buffers_1{nullptr, 0}, - boost::asio::const_buffers_1{nullptr, 0}, - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, field_range(f_.list_.begin(), f_.list_.end()), chunk_crlf()); } @@ -218,11 +218,11 @@ reader(basic_fields const& f, buf_[10]= '\n'; view_.emplace( - boost::asio::const_buffers_1{sv.data(), sv.size()}, - boost::asio::const_buffers_1{ + boost::asio::const_buffer{sv.data(), sv.size()}, + boost::asio::const_buffer{ f_.target_or_reason_.data(), f_.target_or_reason_.size()}, - boost::asio::const_buffers_1{buf_, 11}, + boost::asio::const_buffer{buf_, 11}, field_range(f_.list_.begin(), f_.list_.end()), chunk_crlf()); } @@ -260,9 +260,9 @@ reader(basic_fields const& f, sv = obsolete_reason(static_cast(code)); view_.emplace( - boost::asio::const_buffers_1{buf_, 13}, - boost::asio::const_buffers_1{sv.data(), sv.size()}, - boost::asio::const_buffers_1{"\r\n", 2}, + boost::asio::const_buffer{buf_, 13}, + boost::asio::const_buffer{sv.data(), sv.size()}, + boost::asio::const_buffer{"\r\n", 2}, field_range(f_.list_.begin(), f_.list_.end()), chunk_crlf{}); } diff --git a/include/boost/beast/http/impl/file_body_win32.ipp b/include/boost/beast/http/impl/file_body_win32.ipp index 1ef2472e..9c7ae6be 100644 --- a/include/boost/beast/http/impl/file_body_win32.ipp +++ b/include/boost/beast/http/impl/file_body_win32.ipp @@ -12,15 +12,15 @@ #if BOOST_BEAST_USE_WIN32_FILE -#include #include #include #include #include +#include +#include +#include #include -#include #include -#include #include #include #include @@ -120,7 +120,7 @@ struct basic_file_body public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template reader(message error_code& ec) { std::size_t nwritten = 0; - for(boost::asio::const_buffer buffer : buffers) + for(auto buffer : beast::detail::buffers_range(buffers)) { nwritten += body_.file_.write( - boost::asio::buffer_cast(buffer), - boost::asio::buffer_size(buffer), - ec); + buffer.data(), buffer.size(), ec); if(ec) return nwritten; } @@ -360,6 +358,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(sock_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, sock_.get_executor()); + } + void operator()(); @@ -368,24 +384,6 @@ public: error_code ec, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, write_some_win32_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_some_win32_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(write_some_win32_op* op) { @@ -393,15 +391,6 @@ public: return asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, write_some_win32_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template< @@ -431,7 +420,7 @@ operator()() r.body_.last_ - r.pos_, sr_.limit())), 2147483646); boost::asio::windows::overlapped_ptr overlapped{ - sock_.get_io_service(), *this}; + sock_.get_executor().context(), *this}; auto& ov = *overlapped.get(); ov.Offset = lowPart(r.pos_); ov.OffsetHigh = highPart(r.pos_); @@ -567,21 +556,20 @@ template< class Protocol, bool isRequest, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some( boost::asio::basic_stream_socket& sock, serializer, Fields>& sr, WriteHandler&& handler) { - async_completion init{handler}; detail::write_some_win32_op< Protocol, - handler_type, + BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void(error_code, std::size_t)), isRequest, Fields>{ init.completion_handler, sock, sr}(); return init.result.get(); diff --git a/include/boost/beast/http/impl/read.ipp b/include/boost/beast/http/impl/read.ipp index de5f963c..7a639266 100644 --- a/include/boost/beast/http/impl/read.ipp +++ b/include/boost/beast/http/impl/read.ipp @@ -18,9 +18,10 @@ #include #include #include -#include +#include +#include #include -#include +#include #include #include #include @@ -61,29 +62,29 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(read_some_op* op) { @@ -92,15 +93,6 @@ public: asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, read_some_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template= 2) goto upcall; state_ = 3; - return s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); case 3: @@ -231,29 +224,29 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, read_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(read_op* op) { @@ -262,15 +255,6 @@ public: asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, read_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->s.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->s.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, read_msg_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_msg_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(read_msg_op* op) { @@ -392,15 +377,6 @@ public: asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, read_msg_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); BOOST_ASSERT(! parser.is_done()); error_code ec; @@ -482,7 +459,8 @@ read_some( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); BOOST_ASSERT(! parser.is_done()); std::size_t bytes_transferred = 0; @@ -541,8 +519,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -async_return_type< - ReadHandler, void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_some( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -551,13 +529,14 @@ async_read_some( { static_assert(is_async_read_stream::value, "AsyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); BOOST_ASSERT(! parser.is_done()); - async_completion init{handler}; + boost::asio::async_completion init{handler}; detail::read_some_op>{ + DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void(error_code, std::size_t))>{ init.completion_handler, stream, buffer, parser}(); return init.result.get(); } @@ -576,7 +555,8 @@ read_header( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); error_code ec; auto const bytes_transferred = @@ -599,7 +579,8 @@ read_header( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(false); if(parser.is_header_done()) @@ -624,9 +605,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -async_return_type< - ReadHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_header( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -635,14 +615,15 @@ async_read_header( { static_assert(is_async_read_stream::value, "AsyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(false); - async_completion init{handler}; detail::read_op>{ + BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{ init.completion_handler, stream, buffer, parser}(); return init.result.get(); } @@ -661,7 +642,8 @@ read( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); error_code ec; auto const bytes_transferred = @@ -684,7 +666,8 @@ read( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(true); if(parser.is_done()) @@ -709,9 +692,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -async_return_type< - ReadHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -720,15 +702,16 @@ async_read( { static_assert(is_async_read_stream::value, "AsyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(true); - async_completion< + boost::asio::async_completion< ReadHandler, void(error_code, std::size_t)> init{handler}; detail::read_op>{ + BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{ init.completion_handler, stream, buffer, parser}(); return init.result.get(); } @@ -747,7 +730,8 @@ read( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); static_assert(is_body::value, "Body requirements not met"); @@ -774,7 +758,8 @@ read( { static_assert(is_sync_read_stream::value, "SyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); static_assert(is_body::value, "Body requirements not met"); @@ -795,9 +780,8 @@ template< class DynamicBuffer, bool isRequest, class Body, class Allocator, class ReadHandler> -async_return_type< - ReadHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -806,21 +790,22 @@ async_read( { static_assert(is_async_read_stream::value, "AsyncReadStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); static_assert(is_body::value, "Body requirements not met"); static_assert(is_body_writer::value, "BodyWriter requirements not met"); - async_completion< + boost::asio::async_completion< ReadHandler, void(error_code, std::size_t)> init{handler}; detail::read_msg_op< AsyncReadStream, DynamicBuffer, isRequest, Body, Allocator, - handler_type>{ + BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void(error_code, std::size_t))>{ init.completion_handler, stream, buffer, msg}(); return init.result.get(); } diff --git a/include/boost/beast/http/impl/serializer.ipp b/include/boost/beast/http/impl/serializer.ipp index c6d0be86..ccbaa248 100644 --- a/include/boost/beast/http/impl/serializer.ipp +++ b/include/boost/beast/http/impl/serializer.ipp @@ -166,12 +166,12 @@ next(error_code& ec, Visit&& visit) boost::in_place_init, frd_->get(), buffer_size(result->first), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}, result->first, chunk_crlf{}, detail::chunk_last(), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}); goto go_all_c; } @@ -179,7 +179,7 @@ next(error_code& ec, Visit&& visit) boost::in_place_init, frd_->get(), buffer_size(result->first), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}, result->first, chunk_crlf{}); @@ -216,19 +216,19 @@ next(error_code& ec, Visit&& visit) v_.template emplace<6>( boost::in_place_init, buffer_size(result->first), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}, result->first, chunk_crlf{}, detail::chunk_last(), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}); goto go_body_final_c; } v_.template emplace<5>( boost::in_place_init, buffer_size(result->first), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}, result->first, chunk_crlf{}); @@ -257,7 +257,7 @@ next(error_code& ec, Visit&& visit) v_.template emplace<8>( boost::in_place_init, detail::chunk_last(), - boost::asio::const_buffers_1{nullptr, 0}, + boost::asio::const_buffer{nullptr, 0}, chunk_crlf{}); s_ = do_final_c + 1; BOOST_BEAST_FALLTHROUGH; diff --git a/include/boost/beast/http/impl/write.ipp b/include/boost/beast/http/impl/write.ipp index 617f4cde..792045fc 100644 --- a/include/boost/beast/http/impl/write.ipp +++ b/include/boost/beast/http/impl/write.ipp @@ -16,9 +16,10 @@ #include #include #include -#include +#include +#include #include -#include +#include #include #include #include @@ -77,6 +78,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()(); @@ -85,24 +104,6 @@ public: error_code ec, std::size_t bytes_transferred); - friend - void* asio_handler_allocate( - std::size_t size, write_some_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_some_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(write_some_op* op) { @@ -110,14 +111,6 @@ public: return asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, write_some_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke(f, std::addressof(op->h_)); - } }; template< @@ -136,7 +129,8 @@ operator()() if(ec) { BOOST_ASSERT(! f.invoked); - return s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); } if(f.invoked) @@ -148,7 +142,8 @@ operator()() // What else could it be? BOOST_ASSERT(sr_.is_done()); } - return s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); } @@ -218,29 +213,29 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, write_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(write_op* op) { @@ -249,15 +244,6 @@ public: asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, write_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template< @@ -278,7 +264,8 @@ operator()( if(Predicate{}(sr_)) { state_ = 1; - return s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); } state_ = 2; @@ -338,6 +325,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->s.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->s.get_executor()); + } + void operator()(); @@ -345,24 +350,6 @@ public: operator()( error_code ec, std::size_t bytes_transferred); - friend - void* asio_handler_allocate( - std::size_t size, write_msg_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_msg_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(write_msg_op* op) { @@ -370,15 +357,6 @@ public: return asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, write_msg_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some( AsyncWriteStream& stream, serializer& sr, WriteHandler&& handler) { - async_completion< + boost::asio::async_completion< WriteHandler, void(error_code, std::size_t)> init{handler}; detail::write_some_op< AsyncWriteStream, - handler_type, + BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void(error_code, std::size_t)), isRequest, Body, Fields>{ init.completion_handler, stream, sr}(); return init.result.get(); @@ -551,9 +528,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some( AsyncWriteStream& stream, serializer& sr, @@ -635,9 +611,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_header( AsyncWriteStream& stream, serializer& sr, @@ -651,13 +626,13 @@ async_write_header( static_assert(is_body_reader::value, "BodyReader requirements not met"); sr.split(true); - async_completion< + boost::asio::async_completion< WriteHandler, void(error_code, std::size_t)> init{handler}; detail::write_op< AsyncWriteStream, - handler_type, + BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void(error_code, std::size_t)), detail::serializer_is_header_done, isRequest, Body, Fields>{ init.completion_handler, stream, sr}(); @@ -713,9 +688,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write( AsyncWriteStream& stream, serializer& sr, @@ -729,13 +703,13 @@ async_write( static_assert(is_body_reader::value, "BodyReader requirements not met"); sr.split(false); - async_completion< + boost::asio::async_completion< WriteHandler, void(error_code, std::size_t)> init{handler}; detail::write_op< AsyncWriteStream, - handler_type, + BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void(error_code, std::size_t)), detail::serializer_is_done, isRequest, Body, Fields>{ init.completion_handler, stream, sr}(); @@ -789,9 +763,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write( AsyncWriteStream& stream, message& msg, @@ -804,13 +777,13 @@ async_write( "Body requirements not met"); static_assert(is_body_reader::value, "BodyReader requirements not met"); - async_completion< + boost::asio::async_completion< WriteHandler, void(error_code, std::size_t)> init{handler}; detail::write_msg_op< AsyncWriteStream, - handler_type, + BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void(error_code, std::size_t)), isRequest, Body, Fields>{ init.completion_handler, stream, msg}(); return init.result.get(); @@ -843,17 +816,13 @@ public: if(os_.fail()) return; std::size_t bytes_transferred = 0; - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - for(auto it = buffers.begin(); - it != buffers.end(); ++it) + for(auto b : buffers_range(buffers)) { - boost::asio::const_buffer b = *it; - auto const n = buffer_size(b); - os_.write(buffer_cast(b), n); + os_.write(reinterpret_cast( + b.data()), b.size()); if(os_.fail()) return; - bytes_transferred += n; + bytes_transferred += b.size(); } sr_.consume(bytes_transferred); } diff --git a/include/boost/beast/http/read.hpp b/include/boost/beast/http/read.hpp index 58b7cf9f..96f2fff0 100644 --- a/include/boost/beast/http/read.hpp +++ b/include/boost/beast/http/read.hpp @@ -11,10 +11,10 @@ #define BOOST_BEAST_HTTP_READ_HPP #include -#include #include #include #include +#include namespace boost { namespace beast { @@ -185,7 +185,7 @@ read_some( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. The completion handler will receive as a parameter the number of octets processed from the dynamic buffer. The octets should @@ -197,12 +197,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - ReadHandler, void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_some( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -375,7 +371,7 @@ read_header( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @note The implementation will call @ref basic_parser::eager with the value `false` on the parser passed in. @@ -385,12 +381,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - ReadHandler, void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_header( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -563,7 +555,7 @@ read( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @note The implementation will call @ref basic_parser::eager with the value `true` on the parser passed in. @@ -573,13 +565,8 @@ template< class DynamicBuffer, bool isRequest, class Derived, class ReadHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - ReadHandler, - void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read( AsyncReadStream& stream, DynamicBuffer& buffer, @@ -754,20 +741,15 @@ read( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class AsyncReadStream, class DynamicBuffer, bool isRequest, class Body, class Allocator, class ReadHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - ReadHandler, - void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read( AsyncReadStream& stream, DynamicBuffer& buffer, diff --git a/include/boost/beast/http/serializer.hpp b/include/boost/beast/http/serializer.hpp index e375f163..2ba86608 100644 --- a/include/boost/beast/http/serializer.hpp +++ b/include/boost/beast/http/serializer.hpp @@ -132,7 +132,7 @@ private: using cb4_t = buffers_suffix>; // crlf @@ -140,7 +140,7 @@ private: using cb5_t = buffers_suffix>; // crlf @@ -148,30 +148,30 @@ private: using cb6_t = buffers_suffix>; // crlf using pcb6_t = buffers_prefix_view; using cb7_t = buffers_suffix>; // crlf using pcb7_t = buffers_prefix_view; using cb8_t = buffers_suffix>; // crlf using pcb8_t = buffers_prefix_view; diff --git a/include/boost/beast/http/span_body.hpp b/include/boost/beast/http/span_body.hpp index a2dd81f9..9af836af 100644 --- a/include/boost/beast/http/span_body.hpp +++ b/include/boost/beast/http/span_body.hpp @@ -72,7 +72,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit diff --git a/include/boost/beast/http/string_body.hpp b/include/boost/beast/http/string_body.hpp index e8a38ce1..28a337b7 100644 --- a/include/boost/beast/http/string_body.hpp +++ b/include/boost/beast/http/string_body.hpp @@ -80,7 +80,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit @@ -172,13 +172,11 @@ public: } ec.assign(0, ec.category()); CharT* dest = &body_[size]; - for(boost::asio::const_buffer b : buffers) + for(auto b : beast::detail::buffers_range(buffers)) { - using boost::asio::buffer_cast; - auto const len = boost::asio::buffer_size(b); - Traits::copy( - dest, buffer_cast(b), len); - dest += len; + Traits::copy(dest, reinterpret_cast< + CharT const*>(b.data()), b.size()); + dest += b.size(); } return extra; } diff --git a/include/boost/beast/http/type_traits.hpp b/include/boost/beast/http/type_traits.hpp index 1328c7f3..7b2fd4d7 100644 --- a/include/boost/beast/http/type_traits.hpp +++ b/include/boost/beast/http/type_traits.hpp @@ -88,7 +88,7 @@ struct is_body_reader>&>() = std::declval().get(std::declval()), (void)0)>> : std::integral_constant::value && std::is_constructible&>::value && @@ -131,7 +131,7 @@ struct is_body_writer()), std::declval() = std::declval().put( - std::declval(), + std::declval(), std::declval()), std::declval().finish( std::declval()), diff --git a/include/boost/beast/http/vector_body.hpp b/include/boost/beast/http/vector_body.hpp index 8e5948dd..91378917 100644 --- a/include/boost/beast/http/vector_body.hpp +++ b/include/boost/beast/http/vector_body.hpp @@ -75,7 +75,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit diff --git a/include/boost/beast/http/write.hpp b/include/boost/beast/http/write.hpp index 964555b6..befc0fe7 100644 --- a/include/boost/beast/http/write.hpp +++ b/include/boost/beast/http/write.hpp @@ -18,8 +18,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -158,7 +158,7 @@ write_some( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @see @ref serializer */ @@ -166,13 +166,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - WriteHandler, - void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some( AsyncWriteStream& stream, serializer& sr, @@ -284,7 +279,7 @@ write_header( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @note The implementation will call @ref serializer::split with the value `true` on the serializer passed in. @@ -295,13 +290,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - WriteHandler, - void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_header( AsyncWriteStream& stream, serializer& sr, @@ -407,7 +397,7 @@ write( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @see @ref serializer */ @@ -415,13 +405,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else -async_return_type< - WriteHandler, - void(error_code, std::size_t)> -#endif +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write( AsyncWriteStream& stream, serializer& sr, @@ -527,7 +512,7 @@ write( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. @see @ref message */ @@ -535,9 +520,8 @@ template< class AsyncWriteStream, bool isRequest, class Body, class Fields, class WriteHandler> -async_return_type< - WriteHandler, - void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write( AsyncWriteStream& stream, message& msg, diff --git a/include/boost/beast/websocket/detail/frame.hpp b/include/boost/beast/websocket/detail/frame.hpp index 19b0f46e..95080aee 100644 --- a/include/boost/beast/websocket/detail/frame.hpp +++ b/include/boost/beast/websocket/detail/frame.hpp @@ -233,10 +233,10 @@ read_ping(ping_data& data, Buffers const& bs) { using boost::asio::buffer_copy; using boost::asio::buffer_size; - using boost::asio::mutable_buffers_1; + using boost::asio::mutable_buffer; BOOST_ASSERT(buffer_size(bs) <= data.max_size()); data.resize(buffer_size(bs)); - buffer_copy(mutable_buffers_1{ + buffer_copy(mutable_buffer{ data.data(), data.size()}, bs); } diff --git a/include/boost/beast/websocket/detail/mask.hpp b/include/boost/beast/websocket/detail/mask.hpp index a6386f95..e5729aa2 100644 --- a/include/boost/beast/websocket/detail/mask.hpp +++ b/include/boost/beast/websocket/detail/mask.hpp @@ -122,10 +122,8 @@ mask_inplace_fast( boost::asio::mutable_buffer const& b, std::uint32_t& key) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - auto n = buffer_size(b); - auto p = buffer_cast(b); + auto n = b.size(); + auto p = reinterpret_cast(b.data()); if(n >= sizeof(key)) { // Bring p to 4-byte alignment @@ -177,10 +175,8 @@ mask_inplace_fast( boost::asio::mutable_buffer const& b, std::uint64_t& key) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - auto n = buffer_size(b); - auto p = buffer_cast(b); + auto n = b.size(); + auto p = reinterpret_cast(b.data()); if(n >= sizeof(key)) { // Bring p to 8-byte alignment diff --git a/include/boost/beast/websocket/detail/pausation.hpp b/include/boost/beast/websocket/detail/pausation.hpp index 82f7a854..74aa9dfa 100644 --- a/include/boost/beast/websocket/detail/pausation.hpp +++ b/include/boost/beast/websocket/detail/pausation.hpp @@ -11,6 +11,7 @@ #define BOOST_BEAST_WEBSOCKET_DETAIL_PAUSATION_HPP #include +#include #include #include #include @@ -88,13 +89,16 @@ class pausation public: ~saved_op() { - using boost::asio::asio_handler_deallocate; if(op_) { Op op(std::move(*op_)); op_->~Op(); - asio_handler_deallocate(op_, - sizeof(*op_), std::addressof(op.handler())); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator(op)}; + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, op_, 1); } } @@ -115,10 +119,13 @@ class pausation explicit saved_op(Op&& op) { - using boost::asio::asio_handler_allocate; - op_ = new(asio_handler_allocate(sizeof(Op), - std::addressof(op.handler()))) Op{ - std::move(op)}; + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator(op)}; + auto const p = std::allocator_traits< + decltype(alloc)>::allocate(alloc, 1); + op_ = new(p) Op{std::move(op)}; } void @@ -126,9 +133,12 @@ class pausation { BOOST_ASSERT(op_); Op op{std::move(*op_)}; - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(op_, - sizeof(*op_), std::addressof(op_->handler())); + typename std::allocator_traits< + boost::asio::associated_allocator_t>:: + template rebind_alloc alloc{ + boost::asio::get_associated_allocator(op)}; + std::allocator_traits< + decltype(alloc)>::deallocate(alloc, op_, 1); op_ = nullptr; op(); } diff --git a/include/boost/beast/websocket/detail/pmd_extension.hpp b/include/boost/beast/websocket/detail/pmd_extension.hpp index 6342eb14..4aab7f50 100644 --- a/include/boost/beast/websocket/detail/pmd_extension.hpp +++ b/include/boost/beast/websocket/detail/pmd_extension.hpp @@ -371,33 +371,31 @@ deflate( error_code& ec) { using boost::asio::buffer; - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - BOOST_ASSERT(buffer_size(out) >= 6); + BOOST_ASSERT(out.size() >= 6); zlib::z_params zs; zs.avail_in = 0; zs.next_in = nullptr; - zs.avail_out = buffer_size(out); - zs.next_out = buffer_cast(out); - for(boost::asio::const_buffer in : cb) + zs.avail_out = out.size(); + zs.next_out = out.data(); + for(auto in : beast::detail::buffers_range(cb)) { - zs.avail_in = buffer_size(in); + zs.avail_in = in.size(); if(zs.avail_in == 0) continue; - zs.next_in = buffer_cast(in); + zs.next_in = in.data(); zo.write(zs, zlib::Flush::none, ec); if(ec) { if(ec != zlib::error::need_buffers) return false; BOOST_ASSERT(zs.avail_out == 0); - BOOST_ASSERT(zs.total_out == buffer_size(out)); + BOOST_ASSERT(zs.total_out == out.size()); ec.assign(0, ec.category()); break; } if(zs.avail_out == 0) { - BOOST_ASSERT(zs.total_out == buffer_size(out)); + BOOST_ASSERT(zs.total_out == out.size()); break; } BOOST_ASSERT(zs.avail_in == 0); @@ -406,7 +404,7 @@ deflate( cb.consume(zs.total_in); if(zs.avail_out > 0 && fin) { - auto const remain = buffer_size(cb); + auto const remain = boost::asio::buffer_size(cb); if(remain == 0) { // Inspired by Mark Adler @@ -426,15 +424,13 @@ deflate( BOOST_ASSERT(! ec); // remove flush marker zs.total_out -= 4; - out = buffer( - buffer_cast(out), zs.total_out); + out = buffer(out.data(), zs.total_out); return false; } } } ec.assign(0, ec.category()); - out = buffer( - buffer_cast(out), zs.total_out); + out = buffer(out.data(), zs.total_out); return true; } diff --git a/include/boost/beast/websocket/detail/utf8_checker.hpp b/include/boost/beast/websocket/detail/utf8_checker.hpp index 9d1b9ce9..08f35a6e 100644 --- a/include/boost/beast/websocket/detail/utf8_checker.hpp +++ b/include/boost/beast/websocket/detail/utf8_checker.hpp @@ -86,13 +86,12 @@ bool utf8_checker_t<_>:: write(ConstBufferSequence const& bs) { - static_assert(is_const_buffer_sequence::value, + static_assert(boost::asio::is_const_buffer_sequence::value, "ConstBufferSequence requirements not met"); - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - for(boost::asio::const_buffer b : bs) - if(! write(buffer_cast(b), - buffer_size(b))) + for(auto b : beast::detail::buffers_range(bs)) + if(! write(reinterpret_cast< + std::uint8_t const*>(b.data()), + b.size())) return false; return true; } diff --git a/include/boost/beast/websocket/impl/accept.ipp b/include/boost/beast/websocket/impl/accept.ipp index c701e685..c6429382 100644 --- a/include/boost/beast/websocket/impl/accept.ipp +++ b/include/boost/beast/websocket/impl/accept.ipp @@ -20,9 +20,10 @@ #include #include #include -#include +#include +#include #include -#include +#include #include #include #include @@ -67,28 +68,28 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->ws.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->ws.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, response_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, response_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(response_op* op) { @@ -96,15 +97,6 @@ public: return asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, response_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template @@ -171,6 +163,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->ws.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->ws.get_executor()); + } + template void run(Buffers const& buffers); @@ -178,24 +188,6 @@ public: error_code ec = {}, std::size_t bytes_used = 0); - friend - void* asio_handler_allocate( - std::size_t size, accept_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, accept_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(accept_op* op) { @@ -203,15 +195,6 @@ public: return asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, accept_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template @@ -256,7 +239,8 @@ operator()(error_code ec, std::size_t) if(ec) { BOOST_ASIO_CORO_YIELD - d.ws.get_io_service().post( + boost::asio::post( + d.ws.get_executor(), bind_handler(std::move(*this), ec)); } else @@ -269,7 +253,7 @@ operator()(error_code ec, std::size_t) ec = error::closed; if(! ec) { - // Arguments from our step must be + // Arguments from our state must be // moved to the stack before releasing // the handler. auto& ws = d.ws; @@ -359,7 +343,7 @@ accept(ConstBufferSequence const& buffers) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); error_code ec; @@ -381,7 +365,7 @@ accept_ex( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); static_assert(detail::is_ResponseDecorator< @@ -403,7 +387,7 @@ accept( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; @@ -440,10 +424,10 @@ accept_ex( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; @@ -544,22 +528,24 @@ accept_ex( template template< class AcceptHandler> -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) stream:: async_accept( AcceptHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - async_completion init{handler}; reset(); accept_op< decltype(&default_decorate_res), - handler_type>{ - init.completion_handler, - *this, - &default_decorate_res}({}); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + &default_decorate_res}({}); return init.result.get(); } @@ -567,7 +553,8 @@ template template< class ResponseDecorator, class AcceptHandler> -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) stream:: async_accept_ex( ResponseDecorator const& decorator, @@ -578,15 +565,16 @@ async_accept_ex( static_assert(detail::is_ResponseDecorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - async_completion init{handler}; reset(); accept_op< ResponseDecorator, - handler_type>{ - init.completion_handler, - *this, - decorator}({}); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + decorator}({}); return init.result.get(); } @@ -596,7 +584,8 @@ template< class AcceptHandler> typename std::enable_if< ! http::detail::is_header::value, - async_return_type>::type + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code))>::type stream:: async_accept( ConstBufferSequence const& buffers, @@ -604,18 +593,19 @@ async_accept( { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - async_completion init{handler}; reset(); accept_op< decltype(&default_decorate_res), - handler_type>{ - init.completion_handler, - *this, - &default_decorate_res}.run(buffers); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + &default_decorate_res}.run(buffers); return init.result.get(); } @@ -626,7 +616,8 @@ template< class AcceptHandler> typename std::enable_if< ! http::detail::is_header::value, - async_return_type>::type + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code))>::type stream:: async_accept_ex( ConstBufferSequence const& buffers, @@ -635,21 +626,22 @@ async_accept_ex( { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); static_assert(detail::is_ResponseDecorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - async_completion init{handler}; reset(); accept_op< ResponseDecorator, - handler_type>{ - init.completion_handler, - *this, - decorator}.run(buffers); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + decorator}.run(buffers); return init.result.get(); } @@ -657,7 +649,8 @@ template template< class Body, class Allocator, class AcceptHandler> -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) stream:: async_accept( http::request> const& req, @@ -665,16 +658,17 @@ async_accept( { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - async_completion init{handler}; reset(); using boost::asio::asio_handler_is_continuation; response_op< - handler_type>{ - init.completion_handler, - *this, - req, - &default_decorate_res}(); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + req, + &default_decorate_res}(); return init.result.get(); } @@ -683,7 +677,8 @@ template< class Body, class Allocator, class ResponseDecorator, class AcceptHandler> -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) stream:: async_accept_ex( http::request> const& req, @@ -695,16 +690,17 @@ async_accept_ex( static_assert(detail::is_ResponseDecorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - async_completion init{handler}; reset(); using boost::asio::asio_handler_is_continuation; response_op< - handler_type>{ - init.completion_handler, - *this, - req, - decorator}(); + BOOST_ASIO_HANDLER_TYPE( + AcceptHandler, void(error_code))>{ + init.completion_handler, + *this, + req, + decorator}(); return init.result.get(); } diff --git a/include/boost/beast/websocket/impl/close.ipp b/include/boost/beast/websocket/impl/close.ipp index c4ce0f28..c5559b20 100644 --- a/include/boost/beast/websocket/impl/close.ipp +++ b/include/boost/beast/websocket/impl/close.ipp @@ -15,10 +15,11 @@ #include #include #include +#include +#include #include -#include #include -#include +#include #include #include @@ -74,30 +75,30 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->ws.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->ws.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0, bool cont = true); - friend - void* asio_handler_allocate( - std::size_t size, close_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, close_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(close_op* op) { @@ -105,15 +106,6 @@ public: return op->d_->cont || asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, close_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template @@ -155,7 +147,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - d.ws.get_io_service().post(std::move(*this)); + boost::asio::post( + d.ws.get_executor(), std::move(*this)); BOOST_ASSERT(d.ws.wr_block_ == d.tok); // Make sure the stream is open @@ -205,7 +198,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - d.ws.get_io_service().post(std::move(*this)); + boost::asio::post( + d.ws.get_executor(), std::move(*this)); BOOST_ASSERT(d.ws.rd_block_ == d.tok); // Make sure the stream is open @@ -322,7 +316,8 @@ operator()( if(! d.cont) { auto& ws = d.ws; - return ws.stream_.get_io_service().post( + return boost::asio::post( + ws.stream_.get_executor(), bind_handler(d_.release_handler(), ec)); } d_.invoke(ec); @@ -440,17 +435,17 @@ close(close_reason const& cr, error_code& ec) template template -async_return_type< - CloseHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + CloseHandler, void(error_code)) stream:: async_close(close_reason const& cr, CloseHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - async_completion init{handler}; - close_op>{ + close_op{ init.completion_handler, *this, cr}( {}, 0, false); return init.result.get(); diff --git a/include/boost/beast/websocket/impl/handshake.ipp b/include/boost/beast/websocket/impl/handshake.ipp index 2e708f21..dc22bfb3 100644 --- a/include/boost/beast/websocket/impl/handshake.ipp +++ b/include/boost/beast/websocket/impl/handshake.ipp @@ -17,10 +17,10 @@ #include #include #include +#include +#include #include -#include #include -#include #include #include #include @@ -75,29 +75,29 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->ws.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->ws.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_used = 0); - friend - void* asio_handler_allocate( - std::size_t size, handshake_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, handshake_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(handshake_op* op) { @@ -105,15 +105,6 @@ public: return asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, handshake_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template @@ -156,8 +147,8 @@ operator()(error_code ec, std::size_t) template template -async_return_type< - HandshakeHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) stream:: async_handshake(string_view host, string_view target, @@ -165,10 +156,10 @@ async_handshake(string_view host, { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - async_completion init{handler}; - handshake_op>{ + handshake_op{ init.completion_handler, *this, nullptr, host, target, &default_decorate_req}(); return init.result.get(); @@ -176,8 +167,8 @@ async_handshake(string_view host, template template -async_return_type< - HandshakeHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) stream:: async_handshake(response_type& res, string_view host, @@ -186,10 +177,10 @@ async_handshake(response_type& res, { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - async_completion init{handler}; - handshake_op>{ + handshake_op{ init.completion_handler, *this, &res, host, target, &default_decorate_req}(); return init.result.get(); @@ -197,8 +188,8 @@ async_handshake(response_type& res, template template -async_return_type< - HandshakeHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) stream:: async_handshake_ex(string_view host, string_view target, @@ -210,10 +201,10 @@ async_handshake_ex(string_view host, static_assert(detail::is_RequestDecorator< RequestDecorator>::value, "RequestDecorator requirements not met"); - async_completion init{handler}; - handshake_op>{ + handshake_op{ init.completion_handler, *this, nullptr, host, target, decorator}(); return init.result.get(); @@ -221,8 +212,8 @@ async_handshake_ex(string_view host, template template -async_return_type< - HandshakeHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) stream:: async_handshake_ex(response_type& res, string_view host, @@ -235,10 +226,10 @@ async_handshake_ex(response_type& res, static_assert(detail::is_RequestDecorator< RequestDecorator>::value, "RequestDecorator requirements not met"); - async_completion init{handler}; - handshake_op>{ + handshake_op{ init.completion_handler, *this, &res, host, target, decorator}(); return init.result.get(); diff --git a/include/boost/beast/websocket/impl/ping.ipp b/include/boost/beast/websocket/impl/ping.ipp index 8ff65280..77d85dde 100644 --- a/include/boost/beast/websocket/impl/ping.ipp +++ b/include/boost/beast/websocket/impl/ping.ipp @@ -15,10 +15,11 @@ #include #include #include +#include +#include #include -#include #include -#include +#include #include #include @@ -74,28 +75,28 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(d_.handler()); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(d_->ws.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + d_.handler(), d_->ws.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, ping_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->d_.handler())); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, ping_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->d_.handler())); - } - friend bool asio_handler_is_continuation(ping_op* op) { @@ -103,15 +104,6 @@ public: return asio_handler_is_continuation( std::addressof(op->d_.handler())); } - - template - friend - void asio_handler_invoke(Function&& f, ping_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->d_.handler())); - } }; template @@ -134,7 +126,8 @@ operator()(error_code ec, std::size_t) if(! d.ws.check_open(ec)) { BOOST_ASIO_CORO_YIELD - d.ws.get_io_service().post( + boost::asio::post( + d.ws.get_executor(), bind_handler(std::move(*this), ec)); goto upcall; } @@ -152,7 +145,8 @@ operator()(error_code ec, std::size_t) // Resume BOOST_ASIO_CORO_YIELD - d.ws.get_io_service().post(std::move(*this)); + boost::asio::post( + d.ws.get_executor(), std::move(*this)); BOOST_ASSERT(d.ws.wr_block_ == d.tok); // Make sure the stream is open @@ -235,17 +229,17 @@ pong(ping_data const& payload, error_code& ec) template template -async_return_type< - WriteHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code)) stream:: async_ping(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - async_completion init{handler}; - ping_op>{ + ping_op{ init.completion_handler, *this, detail::opcode::ping, payload}(); return init.result.get(); @@ -253,17 +247,17 @@ async_ping(ping_data const& payload, WriteHandler&& handler) template template -async_return_type< - WriteHandler, void(error_code)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code)) stream:: async_pong(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - async_completion init{handler}; - ping_op>{ + ping_op{ init.completion_handler, *this, detail::opcode::pong, payload}(); return init.result.get(); diff --git a/include/boost/beast/websocket/impl/read.ipp b/include/boost/beast/websocket/impl/read.ipp index 6b13d037..9cd0a9c9 100644 --- a/include/boost/beast/websocket/impl/read.ipp +++ b/include/boost/beast/websocket/impl/read.ipp @@ -18,10 +18,11 @@ #include #include #include +#include +#include #include -#include #include -#include +#include #include #include #include @@ -74,6 +75,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(ws_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, ws_.get_executor()); + } + Handler& handler() { @@ -85,24 +104,6 @@ public: std::size_t bytes_transferred = 0, bool cont = true); - friend - void* asio_handler_allocate( - std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_some_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(p, size, - std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(read_some_op* op) { @@ -110,15 +111,6 @@ public: return op->cont_ || asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, read_some_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template @@ -133,7 +125,6 @@ operator()( { using beast::detail::clamp; using boost::asio::buffer; - using boost::asio::buffer_cast; using boost::asio::buffer_size; close_code code{}; cont_ = cont; @@ -168,7 +159,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - ws_.get_io_service().post(std::move(*this)); + boost::asio::post( + ws_.get_executor(), std::move(*this)); BOOST_ASSERT(ws_.rd_block_ == tok_); // The only way to get read blocked is if @@ -290,7 +282,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - ws_.get_io_service().post(std::move(*this)); + boost::asio::post( + ws_.get_executor(), std::move(*this)); BOOST_ASSERT(ws_.wr_block_ == tok_); // Make sure the stream is open @@ -489,8 +482,8 @@ operator()( zlib::z_params zs; { auto const out = buffers_front(cb_); - zs.next_out = buffer_cast(out); - zs.avail_out = buffer_size(out); + zs.next_out = out.data(); + zs.avail_out = out.size(); BOOST_ASSERT(zs.avail_out > 0); } if(ws_.rd_remain_ > 0) @@ -501,8 +494,8 @@ operator()( auto const in = buffers_prefix( clamp(ws_.rd_remain_), buffers_front( ws_.rd_buf_.data())); - zs.avail_in = buffer_size(in); - zs.next_in = buffer_cast(in); + zs.avail_in = in.size(); + zs.next_in = in.data(); } else { @@ -594,7 +587,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - ws_.get_io_service().post(std::move(*this)); + boost::asio::post( + ws_.get_executor(), std::move(*this)); BOOST_ASSERT(ws_.wr_block_ == tok_); // Make sure the stream is open @@ -659,7 +653,8 @@ operator()( ws_.paused_wr_.maybe_invoke(); } if(! cont_) - return ws_.stream_.get_io_service().post( + return boost::asio::post( + ws_.stream_.get_executor(), bind_handler(std::move(h_), ec, bytes_written_)); h_(ec, bytes_written_); @@ -683,6 +678,9 @@ class stream::read_op bool some_; public: + using allocator_type = + boost::asio::associated_allocator_t; + read_op(read_op&&) = default; read_op(read_op const&) = default; @@ -702,28 +700,25 @@ public: { } + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(ws_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, ws_.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate( - std::size_t size, read_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(read_op* op) { @@ -731,15 +726,6 @@ public: return asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, read_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template @@ -771,7 +757,8 @@ operator()( if(ec) { BOOST_ASIO_CORO_YIELD - ws_.get_io_service().post( + boost::asio::post( + ws_.get_executor(), bind_handler(std::move(*this), error::buffer_overflow, 0)); break; @@ -800,7 +787,8 @@ read(DynamicBuffer& buffer) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); error_code ec; auto const bytes_written = read(buffer, ec); @@ -817,7 +805,8 @@ read(DynamicBuffer& buffer, error_code& ec) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); std::size_t bytes_written = 0; do @@ -832,24 +821,27 @@ read(DynamicBuffer& buffer, error_code& ec) template template -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) stream:: async_read(DynamicBuffer& buffer, ReadHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); - async_completion< + boost::asio::async_completion< ReadHandler, void(error_code, std::size_t)> init{handler}; read_op< DynamicBuffer, - handler_type >{ - init.completion_handler, - *this, - buffer, - 0, - false}(); + BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void(error_code, std::size_t))>{ + init.completion_handler, + *this, + buffer, + 0, + false}(); return init.result.get(); } @@ -865,7 +857,8 @@ read_some( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); error_code ec; auto const bytes_written = @@ -886,7 +879,8 @@ read_some( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); using beast::detail::clamp; if(! limit) @@ -912,8 +906,8 @@ read_some( template template -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) stream:: async_read_some( DynamicBuffer& buffer, @@ -922,19 +916,20 @@ async_read_some( { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); - async_completion init{handler}; read_op< DynamicBuffer, - handler_type>{ - init.completion_handler, - *this, - buffer, - limit, - true}({}, 0); + BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void(error_code, std::size_t))>{ + init.completion_handler, + *this, + buffer, + limit, + true}({}, 0); return init.result.get(); } @@ -949,7 +944,7 @@ read_some( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); error_code ec; @@ -969,12 +964,11 @@ read_some( { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); using beast::detail::clamp; using boost::asio::buffer; - using boost::asio::buffer_cast; using boost::asio::buffer_size; close_code code{}; std::size_t bytes_written = 0; @@ -1191,8 +1185,8 @@ loop: zlib::z_params zs; { auto const out = buffers_front(cb); - zs.next_out = buffer_cast(out); - zs.avail_out = buffer_size(out); + zs.next_out = out.data(); + zs.avail_out = out.size(); BOOST_ASSERT(zs.avail_out > 0); } if(rd_remain_ > 0) @@ -1203,8 +1197,8 @@ loop: auto const in = buffers_prefix( clamp(rd_remain_), buffers_front( rd_buf_.data())); - zs.avail_in = buffer_size(in); - zs.next_in = buffer_cast(in); + zs.avail_in = in.size(); + zs.next_in = in.data(); } else if(! did_read) { @@ -1225,8 +1219,8 @@ loop: auto const in = buffers_prefix( clamp(rd_remain_), buffers_front( rd_buf_.data())); - zs.avail_in = buffer_size(in); - zs.next_in = buffer_cast(in); + zs.avail_in = in.size(); + zs.next_in = in.data(); did_read = true; } else @@ -1299,7 +1293,8 @@ loop: template template -async_return_type +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) stream:: async_read_some( MutableBufferSequence const& buffers, @@ -1307,13 +1302,13 @@ async_read_some( { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); - async_completion init{handler}; - read_some_op>{ + read_some_op{ init.completion_handler,*this, buffers}( {}, 0, false); return init.result.get(); diff --git a/include/boost/beast/websocket/impl/stream.ipp b/include/boost/beast/websocket/impl/stream.ipp index 65a1831c..f8e4a5fc 100644 --- a/include/boost/beast/websocket/impl/stream.ipp +++ b/include/boost/beast/websocket/impl/stream.ipp @@ -91,7 +91,8 @@ std::size_t stream:: read_size_hint(DynamicBuffer& buffer) const { - static_assert(is_dynamic_buffer::value, + static_assert( + boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); auto const initial_size = (std::min)( +tcp_frame_size, @@ -503,7 +504,7 @@ write_ping(DynamicBuffer& db, detail::prepare_key(key, fh.key); auto mb = db.prepare(data.size()); boost::asio::buffer_copy(mb, - boost::asio::const_buffers_1( + boost::asio::const_buffer( data.data(), data.size())); if(fh.mask) detail::mask_inplace(mb, key); diff --git a/include/boost/beast/websocket/impl/teardown.ipp b/include/boost/beast/websocket/impl/teardown.ipp index 71622256..bf7f418e 100644 --- a/include/boost/beast/websocket/impl/teardown.ipp +++ b/include/boost/beast/websocket/impl/teardown.ipp @@ -12,9 +12,10 @@ #include #include -#include +#include +#include #include -#include +#include #include namespace boost { @@ -49,29 +50,29 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(s_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, s_.get_executor()); + } + void operator()( error_code ec = {}, std::size_t bytes_transferred = 0); - friend - void* asio_handler_allocate(std::size_t size, - teardown_tcp_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate(void* p, - std::size_t size, teardown_tcp_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(teardown_tcp_op* op) { @@ -79,16 +80,6 @@ public: return op->step_ >= 3 || asio_handler_is_continuation(std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, - teardown_tcp_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template @@ -105,7 +96,8 @@ operator()(error_code ec, std::size_t) if(ec) { step_ = 1; - return s_.get_io_service().post( + return boost::asio::post( + s_.get_executor(), bind_handler(std::move(*this), ec, 0)); } step_ = 2; diff --git a/include/boost/beast/websocket/impl/write.ipp b/include/boost/beast/websocket/impl/write.ipp index cc314c54..0a29c052 100644 --- a/include/boost/beast/websocket/impl/write.ipp +++ b/include/boost/beast/websocket/impl/write.ipp @@ -20,10 +20,10 @@ #include #include #include +#include +#include #include -#include #include -#include #include #include #include @@ -71,6 +71,24 @@ public: { } + using allocator_type = + boost::asio::associated_allocator_t; + + allocator_type + get_allocator() const noexcept + { + return boost::asio::get_associated_allocator(h_); + } + + using executor_type = boost::asio::associated_executor_t< + Handler, decltype(ws_.get_executor())>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + h_, ws_.get_executor()); + } + Handler& handler() { @@ -82,24 +100,6 @@ public: std::size_t bytes_transferred = 0, bool cont = true); - friend - void* asio_handler_allocate( - std::size_t size, write_some_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate( - size, std::addressof(op->h_)); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_some_op* op) - { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate( - p, size, std::addressof(op->h_)); - } - friend bool asio_handler_is_continuation(write_some_op* op) { @@ -107,15 +107,6 @@ public: return op->cont_ || asio_handler_is_continuation( std::addressof(op->h_)); } - - template - friend - void asio_handler_invoke(Function&& f, write_some_op* op) - { - using boost::asio::asio_handler_invoke; - asio_handler_invoke( - f, std::addressof(op->h_)); - } }; template @@ -132,7 +123,7 @@ operator()( using boost::asio::buffer; using boost::asio::buffer_copy; using boost::asio::buffer_size; - using boost::asio::mutable_buffers_1; + using boost::asio::mutable_buffer; enum { do_nomask_nofrag, @@ -225,7 +216,8 @@ operator()( // Resume BOOST_ASIO_CORO_YIELD - ws_.get_io_service().post(std::move(*this)); + boost::asio::post( + ws_.get_executor(), std::move(*this)); BOOST_ASSERT(ws_.wr_block_ == tok_); // Make sure the stream is open @@ -435,8 +427,8 @@ operator()( // Send frame BOOST_ASIO_CORO_YIELD boost::asio::async_write(ws_.stream_, - buffers_cat(ws_.wr_fb_.data(), - mutable_buffers_1{b}), std::move(*this)); + buffers_cat(ws_.wr_fb_.data(), b), + std::move(*this)); if(! ws_.check_ok(ec)) goto upcall; bytes_transferred_ += in_; @@ -478,7 +470,8 @@ operator()( ws_.paused_rd_.maybe_invoke() || ws_.paused_ping_.maybe_invoke(); if(! cont_) - return ws_.stream_.get_io_service().post( + return boost::asio::post( + ws_.stream_.get_executor(), bind_handler(h_, ec, bytes_transferred_)); h_(ec, bytes_transferred_); } @@ -494,7 +487,7 @@ write_some(bool fin, ConstBufferSequence const& buffers) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); error_code ec; @@ -514,7 +507,7 @@ write_some(bool fin, { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); using beast::detail::clamp; @@ -720,21 +713,21 @@ write_some(bool fin, template template -async_return_type< - WriteHandler, void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) stream:: async_write_some(bool fin, ConstBufferSequence const& bs, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - async_completion init{handler}; - write_some_op>{ + write_some_op{ init.completion_handler, *this, fin, bs}( {}, 0, false); return init.result.get(); @@ -750,7 +743,7 @@ write(ConstBufferSequence const& buffers) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); error_code ec; @@ -768,7 +761,7 @@ write(ConstBufferSequence const& buffers, error_code& ec) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); return write_some(true, buffers, ec); @@ -776,21 +769,21 @@ write(ConstBufferSequence const& buffers, error_code& ec) template template -async_return_type< - WriteHandler, void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) stream:: async_write( ConstBufferSequence const& bs, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - async_completion init{handler}; - write_some_op>{ + write_some_op{ init.completion_handler, *this, true, bs}( {}, 0, false); return init.result.get(); diff --git a/include/boost/beast/websocket/ssl.hpp b/include/boost/beast/websocket/ssl.hpp index 6c116a7b..44d5dc80 100644 --- a/include/boost/beast/websocket/ssl.hpp +++ b/include/boost/beast/websocket/ssl.hpp @@ -64,7 +64,7 @@ teardown( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). + manner equivalent to using boost::asio::io_context::post(). */ template diff --git a/include/boost/beast/websocket/stream.hpp b/include/boost/beast/websocket/stream.hpp index f8fb8f9e..8f75d339 100644 --- a/include/boost/beast/websocket/stream.hpp +++ b/include/boost/beast/websocket/stream.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +38,8 @@ #include #include +#include // DEPRECATED + namespace boost { namespace beast { namespace websocket { @@ -91,11 +93,11 @@ enum class frame_type you would write: @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; @endcode Alternatively, you can write: @code - ip::tcp::socket sock{io_service}; + ip::tcp::socket sock{io_context}; websocket::stream ws{sock}; @endcode @@ -289,19 +291,29 @@ public: //-------------------------------------------------------------------------- - /** Return the `io_service` associated with the stream + /** Get the executor associated with the object. + + This function may be used to obtain the executor object that the stream + uses to dispatch handlers for asynchronous operations. - This function may be used to obtain the `io_service` object - that the stream uses to dispatch handlers for asynchronous - operations. + @return A copy of the executor that stream will use to dispatch handlers. - @return A reference to the io_service object that the stream - will use to dispatch handlers. + @note This function participates in overload resolution only if + `NextLayer` has a member function named `get_executor`. */ - boost::asio::io_service& - get_io_service() +#if BOOST_BEAST_DOXYGEN + implementation_defined +#else + template< + class T = next_layer_type, + class = typename std::enable_if< + has_get_executor::value>::type> + auto +#endif + get_executor() noexcept -> + decltype(std::declval().get_executor()) { - return stream_.get_io_service(); + return stream_.get_executor(); } /** Get a reference to the next layer @@ -746,7 +758,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... try { @@ -793,7 +805,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... try { @@ -848,7 +860,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... try { @@ -910,7 +922,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... try { @@ -962,7 +974,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... error_code ec; ws.handshake(host, target, ec); @@ -1008,7 +1020,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... error_code ec; response_type res; @@ -1062,7 +1074,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... error_code ec; ws.handshake("localhost", "/", @@ -1124,7 +1136,7 @@ public: @par Example @code - websocket::stream ws{io_service}; + websocket::stream ws{io_context}; ... error_code ec; response_type res; @@ -1187,15 +1199,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - HandshakeHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) async_handshake( string_view host, string_view target, @@ -1243,15 +1251,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - HandshakeHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) async_handshake( response_type& res, string_view host, @@ -1305,15 +1309,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - HandshakeHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) async_handshake_ex( string_view host, string_view target, @@ -1371,15 +1371,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - HandshakeHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + HandshakeHandler, void(error_code)) async_handshake_ex( response_type& res, string_view host, @@ -1950,15 +1946,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - AcceptHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) async_accept(AcceptHandler&& handler); /** Start reading and responding to a WebSocket HTTP Upgrade request. @@ -2015,17 +2007,13 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class ResponseDecorator, class AcceptHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - AcceptHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) async_accept_ex( ResponseDecorator const& decorator, AcceptHandler&& handler); @@ -2082,7 +2070,7 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class ConstBufferSequence, @@ -2092,7 +2080,8 @@ public: #else typename std::enable_if< ! http::detail::is_header::value, - async_return_type>::type + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code))>::type #endif async_accept( ConstBufferSequence const& buffers, @@ -2159,7 +2148,7 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class ConstBufferSequence, @@ -2170,7 +2159,8 @@ public: #else typename std::enable_if< ! http::detail::is_header::value, - async_return_type>::type + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code))>::type #endif async_accept_ex( ConstBufferSequence const& buffers, @@ -2219,17 +2209,13 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class Body, class Allocator, class AcceptHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - AcceptHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) async_accept( http::request> const& req, @@ -2286,18 +2272,14 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class Body, class Allocator, class ResponseDecorator, class AcceptHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - AcceptHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + AcceptHandler, void(error_code)) async_accept_ex( http::request> const& req, @@ -2409,15 +2391,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - CloseHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + CloseHandler, void(error_code)) async_close(close_reason const& cr, CloseHandler&& handler); /** Send a WebSocket ping frame. @@ -2491,15 +2469,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - WriteHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code)) async_ping(ping_data const& payload, WriteHandler&& handler); /** Send a WebSocket pong frame. @@ -2588,15 +2562,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - WriteHandler, void(error_code)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code)) async_pong(ping_data const& payload, WriteHandler&& handler); //-------------------------------------------------------------------------- @@ -2751,16 +2721,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - ReadHandler, - void(error_code, std::size_t)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read( DynamicBuffer& buffer, ReadHandler&& handler); @@ -2936,15 +2901,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - ReadHandler, void(error_code, std::size_t)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_some( DynamicBuffer& buffer, std::size_t limit, @@ -3113,14 +3074,11 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_some( MutableBufferSequence const& buffers, ReadHandler&& handler); @@ -3257,18 +3215,13 @@ public: Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using `boost::asio::io_service::post`. + manner equivalent to using `boost::asio::io_context::post`. */ template< class ConstBufferSequence, class WriteHandler> -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type< - WriteHandler, - void(error_code, std::size_t)> -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write( ConstBufferSequence const& buffers, WriteHandler&& handler); @@ -3389,12 +3342,8 @@ public: ); @endcode */ template -#if BOOST_BEAST_DOXYGEN - void_or_deduced -#else - async_return_type -#endif + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some(bool fin, ConstBufferSequence const& buffers, WriteHandler&& handler); diff --git a/include/boost/beast/websocket/teardown.hpp b/include/boost/beast/websocket/teardown.hpp index b1ceab81..289b57c8 100644 --- a/include/boost/beast/websocket/teardown.hpp +++ b/include/boost/beast/websocket/teardown.hpp @@ -79,7 +79,7 @@ teardown( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). + manner equivalent to using boost::asio::io_context::post(). */ template< @@ -155,7 +155,7 @@ teardown( Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). + manner equivalent to using boost::asio::io_context::post(). */ template diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index b90e9a36..58ca5e31 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -19,7 +19,6 @@ add_executable (tests-beast-core Jamfile buffer_test.hpp file_test.hpp - async_result.cpp bind_handler.cpp buffered_read_stream.cpp buffers_adapter.cpp @@ -34,7 +33,6 @@ add_executable (tests-beast-core file_win32.cpp flat_buffer.cpp flat_static_buffer.cpp - handler_alloc.cpp handler_ptr.cpp multi_buffer.cpp ostream.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index 661feec0..aa093ef8 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -8,7 +8,6 @@ # local SOURCES = - async_result.cpp bind_handler.cpp buffered_read_stream.cpp buffers_adapter.cpp @@ -23,7 +22,6 @@ local SOURCES = file_win32.cpp flat_buffer.cpp flat_static_buffer.cpp - handler_alloc.cpp handler_ptr.cpp multi_buffer.cpp ostream.cpp diff --git a/test/beast/core/async_result.cpp b/test/beast/core/async_result.cpp deleted file mode 100644 index 163d674b..00000000 --- a/test/beast/core/async_result.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -// Test that header file is self-contained. -#include - -#include -#include -#include - -namespace boost { -namespace beast { -namespace { - -struct handler -{ - void operator()(beast::error_code, std::size_t) const; -}; - -static_assert(detail::is_invocable< - typename async_result::completion_handler_type, - void(error_code, std::size_t)>::value, ""); - -static_assert(std::is_same::return_type>::value, ""); - -static_assert(std::is_constructible< - async_result, - typename async_result::completion_handler_type&>::value, ""); - -} // (anon-ns) -} // beast -} // boost diff --git a/test/beast/core/buffer_test.hpp b/test/beast/core/buffer_test.hpp index 258271d2..d2d78bd5 100644 --- a/test/beast/core/buffer_test.hpp +++ b/test/beast/core/buffer_test.hpp @@ -25,17 +25,15 @@ namespace test { template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::string>::type to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast(b.data()), + b.size()); return s; } @@ -50,7 +48,7 @@ write_buffer(DynamicBuffer& b, string_view s) template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::size_t>::type buffer_count(ConstBufferSequence const& buffers) { @@ -59,7 +57,7 @@ buffer_count(ConstBufferSequence const& buffers) template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::size_t>::type size_pre(ConstBufferSequence const& buffers) { @@ -78,7 +76,7 @@ size_pre(ConstBufferSequence const& buffers) template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::size_t>::type size_post(ConstBufferSequence const& buffers) { @@ -90,7 +88,7 @@ size_post(ConstBufferSequence const& buffers) template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::size_t>::type size_rev_pre(ConstBufferSequence const& buffers) { @@ -102,7 +100,7 @@ size_rev_pre(ConstBufferSequence const& buffers) template typename std::enable_if< - is_const_buffer_sequence::value, + boost::asio::is_const_buffer_sequence::value, std::size_t>::type size_rev_post(ConstBufferSequence const& buffers) { diff --git a/test/beast/core/buffered_read_stream.cpp b/test/beast/core/buffered_read_stream.cpp index a450b0f2..010233ad 100644 --- a/test/beast/core/buffered_read_stream.cpp +++ b/test/beast/core/buffered_read_stream.cpp @@ -31,16 +31,17 @@ class buffered_read_stream_test public: void testSpecialMembers() { - boost::asio::io_service ios; + boost::asio::io_context ioc; { - buffered_read_stream srs(ios); + buffered_read_stream srs(ioc); buffered_read_stream srs2(std::move(srs)); srs = std::move(srs2); - BEAST_EXPECT(&srs.get_io_service() == &ios); - BEAST_EXPECT(&srs.get_io_service() == &srs2.get_io_service()); + BEAST_EXPECT(&srs.get_executor().context() == &ioc); + BEAST_EXPECT( + &srs.get_executor().context() == &srs2.get_executor().context()); } { - test::stream ts{ios}; + test::stream ts{ioc}; buffered_read_stream srs(ts); } } @@ -52,7 +53,7 @@ public: std::size_t n_ = 0; std::size_t cap_; unit_test::suite& suite_; - boost::asio::io_service& ios_; + boost::asio::io_context& ioc_; boost::optional ts_; boost::optional fc_; boost::optionalbuffer().commit(buffer_copy( brs_->buffer().prepare(5), buffer("Hello", 5))); @@ -115,8 +116,8 @@ public: void testAsyncLoop() { - std::make_shared(*this, ios_, 0)->run(); - std::make_shared(*this, ios_, 3)->run(); + std::make_shared(*this, ioc_, 0)->run(); + std::make_shared(*this, ioc_, 3)->run(); } void testRead(yield_context do_yield) @@ -131,7 +132,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts(ios_, fc, ", world!"); + test::stream ts(ioc_, fc, ", world!"); buffered_read_stream< test::stream&, multi_buffer> srs(ts); srs.buffer().commit(buffer_copy( @@ -149,7 +150,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts(ios_, fc, ", world!"); + test::stream ts(ioc_, fc, ", world!"); buffered_read_stream< test::stream&, multi_buffer> srs(ts); srs.capacity(3); @@ -168,7 +169,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts(ios_, fc, ", world!"); + test::stream ts(ioc_, fc, ", world!"); buffered_read_stream< test::stream&, multi_buffer> srs(ts); srs.buffer().commit(buffer_copy( @@ -187,7 +188,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts(ios_, fc, ", world!"); + test::stream ts(ioc_, fc, ", world!"); buffered_read_stream< test::stream&, multi_buffer> srs(ts); srs.capacity(3); diff --git a/test/beast/core/buffers_adapter.cpp b/test/beast/core/buffers_adapter.cpp index 326a2111..b22316ed 100644 --- a/test/beast/core/buffers_adapter.cpp +++ b/test/beast/core/buffers_adapter.cpp @@ -29,20 +29,17 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; - s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + s.reserve(boost::asio::buffer_size(bs)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast< + char const*>(b.data()), b.size()); return s; } void testBuffersAdapter() { using boost::asio::buffer; - using boost::asio::buffer_cast; using boost::asio::buffer_size; using boost::asio::const_buffer; using boost::asio::mutable_buffer; diff --git a/test/beast/core/buffers_cat.cpp b/test/beast/core/buffers_cat.cpp index 7d1c1fef..30f92d49 100644 --- a/test/beast/core/buffers_cat.cpp +++ b/test/beast/core/buffers_cat.cpp @@ -218,26 +218,23 @@ public: void run() override { using boost::asio::const_buffer; - using boost::asio::const_buffers_1; + using boost::asio::const_buffer; using boost::asio::mutable_buffer; - using boost::asio::mutable_buffers_1; struct user_defined : mutable_buffer { }; // Check is_all_const_buffer_sequence BOOST_STATIC_ASSERT( - detail::is_all_const_buffer_sequence::value); + detail::is_all_const_buffer_sequence::value); BOOST_STATIC_ASSERT( - detail::is_all_const_buffer_sequence::value); + detail::is_all_const_buffer_sequence::value); BOOST_STATIC_ASSERT( - detail::is_all_const_buffer_sequence::value); + detail::is_all_const_buffer_sequence::value); BOOST_STATIC_ASSERT( - detail::is_all_const_buffer_sequence::value); + detail::is_all_const_buffer_sequence::value); BOOST_STATIC_ASSERT( - detail::is_all_const_buffer_sequence::value); - BOOST_STATIC_ASSERT( - ! detail::is_all_const_buffer_sequence::value); + ! detail::is_all_const_buffer_sequence::value); // Ensure that concatenating mutable buffer // sequences results in a mutable buffer sequence diff --git a/test/beast/core/buffers_prefix.cpp b/test/beast/core/buffers_prefix.cpp index 82cdbf83..e4c030c2 100644 --- a/test/beast/core/buffers_prefix.cpp +++ b/test/beast/core/buffers_prefix.cpp @@ -25,18 +25,14 @@ BOOST_STATIC_ASSERT( std::declval()))>::value); BOOST_STATIC_ASSERT( - is_const_buffer_sequence()))>::value); + std::declval()))>::value); BOOST_STATIC_ASSERT( std::is_same()))>::value); -BOOST_STATIC_ASSERT( - is_mutable_buffer_sequence()))>::value); class buffers_prefix_test : public beast::unit_test::suite { @@ -97,13 +93,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast(b.data()), + b.size()); return s; } diff --git a/test/beast/core/buffers_suffix.cpp b/test/beast/core/buffers_suffix.cpp index fdd1225b..3d3c87df 100644 --- a/test/beast/core/buffers_suffix.cpp +++ b/test/beast/core/buffers_suffix.cpp @@ -58,10 +58,10 @@ public: { char buf[12]; buffers_suffix< - boost::asio::const_buffers_1> cb1{ + boost::asio::const_buffer> cb1{ boost::in_place_init, buf, sizeof(buf)}; buffers_suffix< - boost::asio::const_buffers_1> cb2{ + boost::asio::const_buffer> cb2{ boost::in_place_init, nullptr, 0}; cb2 = cb1; cb1 = std::move(cb2); @@ -116,11 +116,11 @@ public: testDefaultCtor() { using namespace test; - class test_buffer : public boost::asio::const_buffers_1 + class test_buffer : public boost::asio::const_buffer { public: test_buffer() - : boost::asio::const_buffers_1("\r\n", 2) + : boost::asio::const_buffer("\r\n", 2) { } }; @@ -134,11 +134,11 @@ public: { using namespace test; buffers_suffix> cb( + boost::asio::const_buffer, + boost::asio::const_buffer>> cb( boost::in_place_init, - boost::asio::const_buffers_1("\r", 1), - boost::asio::const_buffers_1("\n", 1)); + boost::asio::const_buffer("\r", 1), + boost::asio::const_buffer("\n", 1)); BEAST_EXPECT(to_string(cb) == "\r\n"); } diff --git a/test/beast/core/flat_buffer.cpp b/test/beast/core/flat_buffer.cpp index 23a9b820..87ff033b 100644 --- a/test/beast/core/flat_buffer.cpp +++ b/test/beast/core/flat_buffer.cpp @@ -22,8 +22,8 @@ namespace boost { namespace beast { -static_assert(is_dynamic_buffer::value, - "DynamicBuffer requirements not met"); +BOOST_STATIC_ASSERT( + boost::asio::is_dynamic_buffer::value); class flat_buffer_test : public beast::unit_test::suite { diff --git a/test/beast/core/flat_static_buffer.cpp b/test/beast/core/flat_static_buffer.cpp index 66f5a907..d68a1906 100644 --- a/test/beast/core/flat_static_buffer.cpp +++ b/test/beast/core/flat_static_buffer.cpp @@ -20,9 +20,8 @@ namespace boost { namespace beast { -static_assert( - is_dynamic_buffer::value, - "DynamicBuffer requirements not met"); +BOOST_STATIC_ASSERT( + boost::asio::is_dynamic_buffer::value); class flat_static_buffer_test : public beast::unit_test::suite { @@ -32,7 +31,6 @@ public: { using namespace test; using boost::asio::buffer; - using boost::asio::buffer_cast; using boost::asio::buffer_size; char buf[12]; std::string const s = "Hello, world"; diff --git a/test/beast/core/handler_alloc.cpp b/test/beast/core/handler_alloc.cpp deleted file mode 100644 index 32defc73..00000000 --- a/test/beast/core/handler_alloc.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -// Test that header file is self-contained. -#include - -#include -#include -#include - -namespace boost { -namespace beast { - -class handler_alloc_test : public beast::unit_test::suite -{ -public: - struct handler - { - void - operator()() const - { - } - }; - - // https://github.com/boostorg/beast/issues/432 - void - testRegression432() - { - handler h; - handler_alloc a{h}; - std::list> v{a}; - v.push_back(1); - v.push_back(2); - v.push_back(3); - } - - void - run() override - { - testRegression432(); - - handler h; - handler h2; - handler_alloc a1{h}; - handler_alloc a2{h2}; - BEAST_EXPECT(a2 == a1); - auto a3 = a1; - BEAST_EXPECT(a3 == a1); - { - std::vector> v(a1); - v.reserve(32); - v.resize(10); - } - } -}; - -BEAST_DEFINE_TESTSUITE(beast,core,handler_alloc); - -} // beast -} // boost diff --git a/test/beast/core/multi_buffer.cpp b/test/beast/core/multi_buffer.cpp index 80ab4af7..982cbef8 100644 --- a/test/beast/core/multi_buffer.cpp +++ b/test/beast/core/multi_buffer.cpp @@ -26,7 +26,8 @@ namespace boost { namespace beast { -BOOST_STATIC_ASSERT(is_dynamic_buffer::value); +BOOST_STATIC_ASSERT( + boost::asio::is_dynamic_buffer::value); class multi_buffer_test : public beast::unit_test::suite { diff --git a/test/beast/core/ostream.cpp b/test/beast/core/ostream.cpp index 65c639c6..0c069a47 100644 --- a/test/beast/core/ostream.cpp +++ b/test/beast/core/ostream.cpp @@ -25,13 +25,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast< + char const*>(b.data()), b.size()); return s; } diff --git a/test/beast/core/static_buffer.cpp b/test/beast/core/static_buffer.cpp index cb6d44db..485ab26c 100644 --- a/test/beast/core/static_buffer.cpp +++ b/test/beast/core/static_buffer.cpp @@ -20,9 +20,8 @@ namespace boost { namespace beast { -static_assert( - is_dynamic_buffer::value, - "DynamicBuffer requirements not met"); +BOOST_STATIC_ASSERT( + boost::asio::is_dynamic_buffer::value); class static_buffer_test : public beast::unit_test::suite { @@ -32,7 +31,6 @@ public: { using namespace test; using boost::asio::buffer; - using boost::asio::buffer_cast; using boost::asio::buffer_size; char buf[12]; std::string const s = "Hello, world"; diff --git a/test/beast/core/type_traits.cpp b/test/beast/core/type_traits.cpp index e3be630a..9411b90e 100644 --- a/test/beast/core/type_traits.cpp +++ b/test/beast/core/type_traits.cpp @@ -121,24 +121,6 @@ BOOST_STATIC_ASSERT(min_all(1u, 2u, static_cast(3)) == 1); } // detail -// -// buffer concepts -// - -namespace { - -struct T {}; - -BOOST_STATIC_ASSERT(is_const_buffer_sequence::value); -BOOST_STATIC_ASSERT(! is_const_buffer_sequence::value); - -BOOST_STATIC_ASSERT(is_mutable_buffer_sequence::value); -BOOST_STATIC_ASSERT(! is_mutable_buffer_sequence::value); - -BOOST_STATIC_ASSERT(is_dynamic_buffer::value); - -} // (anonymous) - // // handler concepts // @@ -169,7 +151,7 @@ struct not_a_stream get_io_service(); }; -BOOST_STATIC_ASSERT(has_get_io_service::value); +BOOST_STATIC_ASSERT(has_get_executor::value); BOOST_STATIC_ASSERT(is_async_read_stream::value); BOOST_STATIC_ASSERT(is_async_write_stream::value); BOOST_STATIC_ASSERT(is_async_stream::value); @@ -177,7 +159,7 @@ BOOST_STATIC_ASSERT(is_sync_read_stream::value); BOOST_STATIC_ASSERT(is_sync_write_stream::value); BOOST_STATIC_ASSERT(is_sync_stream::value); -BOOST_STATIC_ASSERT(! has_get_io_service::value); +BOOST_STATIC_ASSERT(! has_get_executor::value); BOOST_STATIC_ASSERT(! is_async_read_stream::value); BOOST_STATIC_ASSERT(! is_async_write_stream::value); BOOST_STATIC_ASSERT(! is_sync_read_stream::value); diff --git a/test/beast/http/basic_parser.cpp b/test/beast/http/basic_parser.cpp index 349a95c7..a6462379 100644 --- a/test/beast/http/basic_parser.cpp +++ b/test/beast/http/basic_parser.cpp @@ -152,7 +152,7 @@ public: template typename std::enable_if< - is_const_buffer_sequence::value>::type + boost::asio::is_const_buffer_sequence::value>::type parsegrind(ConstBufferSequence const& buffers, Test const& test, bool skip = false) { @@ -213,13 +213,13 @@ public: void parsegrind(string_view msg, Test const& test, bool skip = false) { - parsegrind(boost::asio::const_buffers_1{ + parsegrind(boost::asio::const_buffer{ msg.data(), msg.size()}, test, skip); } template typename std::enable_if< - is_const_buffer_sequence::value>::type + boost::asio::is_const_buffer_sequence::value>::type parsegrind(ConstBufferSequence const& buffers) { parsegrind(buffers, [](Parser const&){}); @@ -241,7 +241,7 @@ public: Parser p; p.eager(true); error_code ec; - buffers_suffix cb{ + buffers_suffix cb{ boost::in_place_init, msg.data(), msg.size()}; auto n = p.put(buffers_prefix(i, cb), ec); if(ec == result) @@ -266,8 +266,8 @@ public: p.eager(true); error_code ec; p.put(buffers_cat( - boost::asio::const_buffers_1{msg.data(), i}, - boost::asio::const_buffers_1{ + boost::asio::const_buffer{msg.data(), i}, + boost::asio::const_buffer{ msg.data() + i, msg.size() - i}), ec); if(! ec) p.put_eof(ec); @@ -887,7 +887,7 @@ public: //-------------------------------------------------------------------------- static - boost::asio::const_buffers_1 + boost::asio::const_buffer buf(string_view s) { return {s.data(), s.size()}; @@ -1140,7 +1140,7 @@ public: error_code ec; test_parser p; p.eager(true); - p.put(boost::asio::const_buffers_1{ + p.put(boost::asio::const_buffer{ s.data(), s.size()}, ec); }); }; @@ -1156,7 +1156,7 @@ public: error_code ec; test_parser p; p.eager(true); - p.put(boost::asio::const_buffers_1{ + p.put(boost::asio::const_buffer{ msg.data(), msg.size()}, ec); BEAST_EXPECTS(! ec, ec.message()); grind(msg); @@ -1173,7 +1173,7 @@ public: error_code ec; test_parser p; p.eager(true); - p.put(boost::asio::const_buffers_1{ + p.put(boost::asio::const_buffer{ msg.data(), msg.size()}, ec); BEAST_EXPECT(ec); grind(msg); diff --git a/test/beast/http/chunk_encode.cpp b/test/beast/http/chunk_encode.cpp index 638ff5a4..ed6ebe8c 100644 --- a/test/beast/http/chunk_encode.cpp +++ b/test/beast/http/chunk_encode.cpp @@ -42,10 +42,10 @@ public: { std::string s; s.reserve(boost::asio::buffer_size(buffers)); - for(boost::asio::const_buffer buffer : buffers) + for(boost::asio::const_buffer b : beast::detail::buffers_range(buffers)) s.append( - boost::asio::buffer_cast(buffer), - boost::asio::buffer_size(buffer)); + reinterpret_cast(b.data()), + b.size()); return s; } @@ -73,7 +73,7 @@ public: BEAST_EXPECT(to_string(t3) == match); } - using cb_t = boost::asio::const_buffers_1; + using cb_t = boost::asio::const_buffer; static cb_t diff --git a/test/beast/http/dynamic_body.cpp b/test/beast/http/dynamic_body.cpp index a81f88b0..14bf3191 100644 --- a/test/beast/http/dynamic_body.cpp +++ b/test/beast/http/dynamic_body.cpp @@ -24,7 +24,7 @@ namespace http { class dynamic_body_test : public beast::unit_test::suite { - boost::asio::io_service ios_; + boost::asio::io_context ioc_; public: template @@ -42,13 +42,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; - s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + s.reserve(boost::asio::buffer_size(bs)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast(b.data()), + b.size()); return s; } @@ -61,7 +59,7 @@ public: "Content-Length: 3\r\n" "\r\n" "xyz"; - test::stream ts(ios_, s); + test::stream ts(ioc_, s); response_parser p; multi_buffer b; read(ts, b, p); diff --git a/test/beast/http/file_body.cpp b/test/beast/http/file_body.cpp index b63a5ce7..c950fa22 100644 --- a/test/beast/http/file_body.cpp +++ b/test/beast/http/file_body.cpp @@ -10,6 +10,7 @@ // Test that header file is self-contained. #include +#include #include #include #include @@ -86,10 +87,10 @@ public: serializer, fields> sr{res}; sr.next(ec, visit); BEAST_EXPECTS(! ec, ec.message()); - auto const cb = *visit.buffer.data().begin(); + auto const b = buffers_front(visit.buffer.data()); string_view const s1{ - boost::asio::buffer_cast(cb), - boost::asio::buffer_size(cb)}; + reinterpret_cast(b.data()), + b.size()}; BEAST_EXPECTS(s1 == s, s1); } } diff --git a/test/beast/http/message_fuzz.hpp b/test/beast/http/message_fuzz.hpp index bbb31d67..cbd1b084 100644 --- a/test/beast/http/message_fuzz.hpp +++ b/test/beast/http/message_fuzz.hpp @@ -503,10 +503,14 @@ public: auto const len = rand(500); ostream(db) << "Content-Length: " << len << "\r\n\r\n"; - for(boost::asio::mutable_buffer b : db.prepare(len)) + auto mb = db.prepare(len); + for(auto it = boost::asio::buffer_sequence_begin(mb); + it != boost::asio::buffer_sequence_end(mb); + ++it) { - auto p = boost::asio::buffer_cast(b); - auto n = boost::asio::buffer_size(b); + boost::asio::mutable_buffer b = *it; + auto p = reinterpret_cast(b.data()); + auto n = b.size(); while(n--) *p++ = static_cast(32 + rand(26+26+10+6)); } @@ -523,10 +527,14 @@ public: len -= n; ostream(db) << to_hex(n) << "\r\n"; - for(boost::asio::mutable_buffer b : db.prepare(n)) + auto mb = db.prepare(n); + for(auto it = boost::asio::buffer_sequence_begin(mb); + it != boost::asio::buffer_sequence_end(mb); + ++it) { - auto p = boost::asio::buffer_cast(b); - auto m = boost::asio::buffer_size(b); + boost::asio::mutable_buffer b = *it; + auto p = reinterpret_cast(b.data()); + auto m = b.size(); while(m--) *p++ = static_cast(32 + rand(26+26+10+6)); } diff --git a/test/beast/http/parser.cpp b/test/beast/http/parser.cpp index 1bef3b27..fb133574 100644 --- a/test/beast/http/parser.cpp +++ b/test/beast/http/parser.cpp @@ -37,7 +37,7 @@ public: parser; static - boost::asio::const_buffers_1 + boost::asio::const_buffer buf(string_view s) { return {s.data(), s.size()}; diff --git a/test/beast/http/read.cpp b/test/beast/http/read.cpp index c58df607..55837762 100644 --- a/test/beast/http/read.cpp +++ b/test/beast/http/read.cpp @@ -48,7 +48,7 @@ public: b.commit(buffer_copy( b.prepare(len), buffer(s, len))); test::fail_counter fc(n); - test::stream ts{ios_, fc}; + test::stream ts{ioc_, fc}; test_parser p(fc); error_code ec = test::error::fail_error; ts.close_remote(); @@ -64,7 +64,7 @@ public: b.commit(buffer_copy( b.prepare(pre), buffer(s, pre))); test::fail_counter fc(n); - test::stream ts{ios_, fc, + test::stream ts{ioc_, fc, std::string(s + pre, len - pre)}; test_parser p(fc); error_code ec = test::error::fail_error; @@ -80,7 +80,7 @@ public: b.commit(buffer_copy( b.prepare(len), buffer(s, len))); test::fail_counter fc(n); - test::stream ts{ios_, fc}; + test::stream ts{ioc_, fc}; test_parser p(fc); error_code ec = test::error::fail_error; ts.close_remote(); @@ -95,7 +95,7 @@ public: b.commit(buffer_copy( b.prepare(len), buffer(s, len))); test::fail_counter fc(n); - test::stream ts{ios_, fc}; + test::stream ts{ioc_, fc}; test_parser p(fc); error_code ec = test::error::fail_error; ts.close_remote(); @@ -111,7 +111,7 @@ public: b.commit(buffer_copy( b.prepare(pre), buffer(s, pre))); test::fail_counter fc(n); - test::stream ts(ios_, fc, + test::stream ts(ioc_, fc, std::string{s + pre, len - pre}); test_parser p(fc); error_code ec = test::error::fail_error; @@ -128,7 +128,7 @@ public: try { multi_buffer b; - test::stream c{ios_, "GET / X"}; + test::stream c{ioc_, "GET / X"}; c.close_remote(); request_parser p; read(c, b, p); @@ -144,7 +144,7 @@ public: testBufferOverflow() { { - test::stream c{ios_}; + test::stream c{ioc_}; ostream(c.buffer()) << "GET / HTTP/1.1\r\n" "Host: localhost\r\n" @@ -167,7 +167,7 @@ public: } } { - test::stream c{ios_}; + test::stream c{ioc_}; ostream(c.buffer()) << "GET / HTTP/1.1\r\n" "Host: localhost\r\n" @@ -254,7 +254,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream c{ios_, fc, + test::stream c{ioc_, fc, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "User-Agent: test\r\n" @@ -277,7 +277,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts{ios_, fc, + test::stream ts{ioc_, fc, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "User-Agent: test\r\n" @@ -296,7 +296,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream c{ios_, fc, + test::stream c{ioc_, fc, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "User-Agent: test\r\n" @@ -318,7 +318,7 @@ public: { { multi_buffer b; - test::stream ts{ios_}; + test::stream ts{ioc_}; request_parser p; error_code ec; ts.close_remote(); @@ -327,7 +327,7 @@ public: } { multi_buffer b; - test::stream ts{ios_}; + test::stream ts{ioc_}; request_parser p; error_code ec; ts.close_remote(); @@ -352,28 +352,28 @@ public: { { // Make sure handlers are not destroyed - // after calling io_service::stop - boost::asio::io_service ios; - test::stream ts{ios, + // after calling io_context::stop + boost::asio::io_context ioc; + test::stream ts{ioc, "GET / HTTP/1.1\r\n\r\n"}; BEAST_EXPECT(handler::count() == 0); multi_buffer b; request m; async_read(ts, b, m, handler{}); BEAST_EXPECT(handler::count() > 0); - ios.stop(); + ioc.stop(); BEAST_EXPECT(handler::count() > 0); - ios.reset(); + ioc.restart(); BEAST_EXPECT(handler::count() > 0); - ios.run_one(); + ioc.run_one(); BEAST_EXPECT(handler::count() == 0); } { // Make sure uninvoked handlers are - // destroyed when calling ~io_service + // destroyed when calling ~io_context { - boost::asio::io_service ios; - test::stream ts{ios, + boost::asio::io_context ioc; + test::stream ts{ioc, "GET / HTTP/1.1\r\n\r\n"}; BEAST_EXPECT(handler::count() == 0); multi_buffer b; @@ -389,7 +389,7 @@ public: void testRegression430() { - test::stream ts{ios_}; + test::stream ts{ioc_}; ts.read_size(1); ostream(ts.buffer()) << "HTTP/1.1 200 OK\r\n" @@ -417,7 +417,7 @@ public: Parser p; error_code ec = test::error::fail_error; flat_buffer b; - test::stream ts{ios_}; + test::stream ts{ioc_}; ostream(ts.buffer()) << s; ts.read_size(n); read(ts, b, p, ec); diff --git a/test/beast/http/serializer.cpp b/test/beast/http/serializer.cpp index 3d364730..7e35f253 100644 --- a/test/beast/http/serializer.cpp +++ b/test/beast/http/serializer.cpp @@ -27,7 +27,7 @@ public: struct reader { using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template reader(message const&); @@ -47,7 +47,7 @@ public: struct reader { using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template reader(message&); diff --git a/test/beast/http/span_body.cpp b/test/beast/http/span_body.cpp index 2dbf2c0f..55d5149e 100644 --- a/test/beast/http/span_body.cpp +++ b/test/beast/http/span_body.cpp @@ -54,13 +54,13 @@ struct span_body_test error_code ec; w.init(boost::none, ec); BEAST_EXPECTS(! ec, ec.message()); - w.put(boost::asio::const_buffers_1{ + w.put(boost::asio::const_buffer{ "123", 3}, ec); BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(buf[0] == '1'); BEAST_EXPECT(buf[1] == '2'); BEAST_EXPECT(buf[2] == '3'); - w.put(boost::asio::const_buffers_1{ + w.put(boost::asio::const_buffer{ "456", 3}, ec); BEAST_EXPECTS(ec == error::buffer_overflow, ec.message()); } diff --git a/test/beast/http/test_parser.hpp b/test/beast/http/test_parser.hpp index 3d65c9c5..76174819 100644 --- a/test/beast/http/test_parser.hpp +++ b/test/beast/http/test_parser.hpp @@ -27,7 +27,7 @@ class test_parser public: using mutable_buffers_type = - boost::asio::mutable_buffers_1; + boost::asio::mutable_buffer; int status = 0; int version = 0; diff --git a/test/beast/http/write.cpp b/test/beast/http/write.cpp index d0e8ebaa..bcd91952 100644 --- a/test/beast/http/write.cpp +++ b/test/beast/http/write.cpp @@ -44,7 +44,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit @@ -89,7 +89,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit @@ -226,7 +226,7 @@ public: public: using const_buffers_type = - boost::asio::const_buffers_1; + boost::asio::const_buffer; template explicit @@ -270,13 +270,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast(b), + b.size()); return s; } @@ -284,7 +282,7 @@ public: bool equal_body(string_view sv, string_view body) { - test::stream ts{ios_, sv}, tr{ios_}; + test::stream ts{ioc_, sv}, tr{ioc_}; ts.connect(tr); message m; multi_buffer b; @@ -305,7 +303,7 @@ public: std::string str(message const& m) { - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); error_code ec; write(ts, m, ec); @@ -325,7 +323,7 @@ public: m.set(field::content_length, "5"); m.body() = "*****"; error_code ec; - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); async_write(ts, m, do_yield[ec]); BEAST_EXPECT(! m.keep_alive()); @@ -345,7 +343,7 @@ public: m.set(field::transfer_encoding, "chunked"); m.body() = "*****"; error_code ec; - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); async_write(ts, m, do_yield[ec]); if(BEAST_EXPECTS(! ec, ec.message())) @@ -369,7 +367,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::stream ts{ios_, fc}, tr{ios_}; + test::stream ts{ioc_, fc}, tr{ioc_}; ts.connect(tr); request m(verb::get, "/", 10, fc); m.set(field::user_agent, "test"); @@ -399,7 +397,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::stream ts{ios_, fc}, tr{ios_}; + test::stream ts{ioc_, fc}, tr{ioc_}; ts.connect(tr); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); @@ -430,7 +428,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::stream ts{ios_, fc}, tr{ios_}; + test::stream ts{ioc_, fc}, tr{ioc_}; ts.connect(tr); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); @@ -461,7 +459,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::stream ts{ios_, fc}, tr{ios_}; + test::stream ts{ioc_, fc}, tr{ioc_}; ts.connect(tr); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); @@ -488,7 +486,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::stream ts{ios_, fc}, tr{ios_}; + test::stream ts{ioc_, fc}, tr{ioc_}; ts.connect(tr); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); @@ -542,7 +540,7 @@ public: m.set(field::user_agent, "test"); m.body() = "*"; m.prepare_payload(); - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); error_code ec; write(ts, m, ec); @@ -581,7 +579,7 @@ public: m.set(field::user_agent, "test"); m.body() = "*"; m.prepare_payload(); - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); error_code ec; write(ts, m, ec); @@ -648,9 +646,9 @@ public: { { // Make sure handlers are not destroyed - // after calling io_service::stop - boost::asio::io_service ios; - test::stream ts{ios}; + // after calling io_context::stop + boost::asio::io_context ioc; + test::stream ts{ioc}; BEAST_EXPECT(handler::count() == 0); request m; m.method(verb::get); @@ -660,19 +658,19 @@ public: m.body() = "*****"; async_write(ts, m, handler{}); BEAST_EXPECT(handler::count() > 0); - ios.stop(); + ioc.stop(); BEAST_EXPECT(handler::count() > 0); - ios.reset(); + ioc.restart(); BEAST_EXPECT(handler::count() > 0); - ios.run_one(); + ioc.run_one(); BEAST_EXPECT(handler::count() == 0); } { // Make sure uninvoked handlers are - // destroyed when calling ~io_service + // destroyed when calling ~io_context { - boost::asio::io_service ios; - test::stream ts{ios}, tr{ios}; + boost::asio::io_context ioc; + test::stream ts{ioc}, tr{ioc}; ts.connect(tr); BEAST_EXPECT(handler::count() == 0); request m; @@ -733,7 +731,7 @@ public: void testWriteStream(boost::asio::yield_context yield) { - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); ts.write_size(3); @@ -849,8 +847,8 @@ public: void testIssue655() { - boost::asio::io_service ios; - test::stream ts{ios}, tr{ios}; + boost::asio::io_context ioc; + test::stream ts{ioc}, tr{ioc}; ts.connect(tr); response res; res.chunked(true); @@ -859,7 +857,7 @@ public: [&](error_code const&, std::size_t) { }); - ios.run(); + ioc.run(); } void diff --git a/test/beast/websocket/accept.cpp b/test/beast/websocket/accept.cpp index b98640a4..71ae0768 100644 --- a/test/beast/websocket/accept.cpp +++ b/test/beast/websocket/accept.cpp @@ -70,7 +70,7 @@ public: // request in stream, oversized { - stream ws{ios_, + stream ws{ioc_, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "Upgrade: websocket\r\n" @@ -115,7 +115,7 @@ public: // request in stream, decorator, oversized { - stream ws{ios_, + stream ws{ioc_, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "Upgrade: websocket\r\n" @@ -158,7 +158,7 @@ public: // request in buffers, oversize { - stream ws{ios_}; + stream ws{ioc_}; auto tr = connect(ws.next_layer()); try { @@ -202,7 +202,7 @@ public: // request in buffers, decorator, oversized { - stream ws{ios_}; + stream ws{ioc_}; auto tr = connect(ws.next_layer()); try { @@ -248,7 +248,7 @@ public: // request in buffers and stream, oversized { - stream ws{ios_, + stream ws{ioc_, "Connection: upgrade\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "Sec-WebSocket-Version: 13\r\n" @@ -294,7 +294,7 @@ public: // request in buffers and stream, decorator, oversize { - stream ws{ios_, + stream ws{ioc_, "Connection: upgrade\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "Sec-WebSocket-Version: 13\r\n" @@ -415,7 +415,7 @@ public: // Closed by client { - stream ws{ios_}; + stream ws{ioc_}; auto tr = connect(ws.next_layer()); tr.close(); try @@ -466,7 +466,7 @@ public: n = s.size() - 1; break; } - stream ws{ios_}; + stream ws{ioc_}; auto tr = connect(ws.next_layer()); ws.next_layer().append( s.substr(n, s.size() - n)); diff --git a/test/beast/websocket/close.cpp b/test/beast/websocket/close.cpp index 494ca42e..2c215206 100644 --- a/test/beast/websocket/close.cpp +++ b/test/beast/websocket/close.cpp @@ -50,7 +50,7 @@ public: // already closed { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); w.handshake(ws, "localhost", "/"); w.close(ws, {}); @@ -96,7 +96,7 @@ public: // drain invalid message frame after close { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); w.handshake(ws, "localhost", "/"); ws.next_layer().append("\x81\x81\xff\xff\xff\xff*"); @@ -116,7 +116,7 @@ public: // drain invalid close frame after close { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); w.handshake(ws, "localhost", "/"); ws.next_layer().append("\x88\x01*"); @@ -136,7 +136,7 @@ public: // drain masked close frame { echo_server es{log, kind::async_client}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.set_option(pmd); es.async_handshake(); @@ -174,8 +174,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -198,7 +198,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -206,8 +206,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -231,7 +231,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -239,8 +239,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a ping and message to the input @@ -258,8 +258,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -272,7 +272,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -280,8 +280,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add an invalid frame to the input @@ -299,8 +299,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -313,7 +313,7 @@ public: BEAST_EXPECT(++count == 2); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -321,8 +321,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a close frame to the input @@ -340,8 +340,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -354,7 +354,7 @@ public: BEAST_EXPECT(++count == 2); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -362,8 +362,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a close frame to the input @@ -398,7 +398,7 @@ public: BEAST_EXPECT(++count == 2); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 3); }); @@ -406,8 +406,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a ping frame to the input @@ -445,7 +445,7 @@ public: BEAST_EXPECT(ws.is_open()); BEAST_EXPECT(ws.wr_block_); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 3); }); @@ -453,8 +453,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -493,7 +493,7 @@ public: ++count; }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 4); }); @@ -501,8 +501,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -554,7 +554,7 @@ public: BEAST_EXPECT(count == 2 || count == 3); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 4); }); @@ -562,8 +562,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -602,7 +602,7 @@ public: BEAST_EXPECT(++count == 2); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 4); }); } @@ -615,7 +615,7 @@ public: void operator()(error_code) {} }; - stream ws{ios_}; + stream ws{ioc_}; stream::close_op op{ handler{}, ws, {}}; using boost::asio::asio_handler_is_continuation; diff --git a/test/beast/websocket/handshake.cpp b/test/beast/websocket/handshake.cpp index a585436b..acf27f91 100644 --- a/test/beast/websocket/handshake.cpp +++ b/test/beast/websocket/handshake.cpp @@ -139,7 +139,7 @@ public: auto const check = [&](std::string const& s) { - stream ws{ios_}; + stream ws{ioc_}; auto tr = connect(ws.next_layer()); ws.next_layer().append(s); tr.close(); diff --git a/test/beast/websocket/ping.cpp b/test/beast/websocket/ping.cpp index 855a5996..4c467816 100644 --- a/test/beast/websocket/ping.cpp +++ b/test/beast/websocket/ping.cpp @@ -42,7 +42,7 @@ public: // ping, already closed { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.close({}); @@ -62,7 +62,7 @@ public: // pong, already closed { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.close({}); @@ -98,8 +98,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -123,7 +123,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -131,8 +131,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -155,7 +155,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -163,8 +163,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a ping and message to the input @@ -182,8 +182,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -196,7 +196,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -204,8 +204,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add an invalid frame to the input @@ -224,8 +224,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -238,7 +238,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -246,8 +246,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a close frame to the input @@ -265,8 +265,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -279,7 +279,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -287,8 +287,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log, kind::async}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // Cause close to be received @@ -305,8 +305,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -319,7 +319,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -328,8 +328,8 @@ public: { echo_server es{log}; error_code ec; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -359,14 +359,14 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 3); }); { echo_server es{log, kind::async}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); @@ -394,7 +394,7 @@ public: ec.message()); }); }); - if(! BEAST_EXPECT(run_until(ios, 100, + if(! BEAST_EXPECT(run_until(ioc, 100, [&]{ return ws.wr_close_; }))) return; // Try to ping @@ -422,10 +422,10 @@ public: { if(count >= 4) break; - ios.run_one(); + ioc.run_one(); } BEAST_EXPECT(n < limit); - ios.run(); + ioc.run(); } } @@ -437,7 +437,7 @@ public: void operator()(error_code) {} }; - stream ws{ios_}; + stream ws{ioc_}; stream::ping_op op{ handler{}, ws, detail::opcode::ping, {}}; using boost::asio::asio_handler_is_continuation; diff --git a/test/beast/websocket/read.cpp b/test/beast/websocket/read.cpp index 33077a33..577fb554 100644 --- a/test/beast/websocket/read.cpp +++ b/test/beast/websocket/read.cpp @@ -76,7 +76,7 @@ public: // already closed { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.close({}); @@ -236,8 +236,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log, kind::async}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // Cause close to be received @@ -252,7 +252,7 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 1); }); @@ -375,7 +375,7 @@ public: [&](error_code ev, string_view s) { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); w.handshake(ws, "localhost", "/"); ws.next_layer().append(s); @@ -619,7 +619,7 @@ public: [&](error_code ev, string_view s) { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.next_layer().append(s); @@ -657,8 +657,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -671,7 +671,7 @@ public: BEAST_EXPECT(++count == 1); }); while(! ws.rd_block_) - ios.run_one(); + ioc.run_one(); multi_buffer b; ws.async_read(b, [&](error_code ec, std::size_t) @@ -681,7 +681,7 @@ public: system_error{ec}); BEAST_EXPECT(++count == 2); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); #endif @@ -691,8 +691,8 @@ public: { //log << "fc.count()==" << fc.count() << std::endl; echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -714,7 +714,7 @@ public: system_error{ec}); BEAST_EXPECT(++count == 1); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -723,8 +723,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // insert a ping @@ -753,7 +753,7 @@ public: ++count; }); BEAST_EXPECT(ws.wr_block_); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -761,8 +761,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -801,7 +801,7 @@ public: BEAST_EXPECT(++count == 2); }); BEAST_EXPECT(ws.wr_block_); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 3); }); @@ -809,8 +809,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -839,7 +839,7 @@ public: BEAST_EXPECT(++count == 1); }); BEAST_EXPECT(ws.wr_block_); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); #endif @@ -852,8 +852,8 @@ public: [&](string_view s) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.next_layer().append(s); @@ -866,8 +866,8 @@ public: // chopped frame header { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.next_layer().append( @@ -883,10 +883,10 @@ public: BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(to_string(b.data()) == s); }); - ios.run_one(); + ioc.run_one(); es.stream().write_some( boost::asio::buffer("\x01" + s)); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 1); } @@ -923,8 +923,8 @@ public: // unmasked frame from client { echo_server es{log, kind::async_client}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); es.async_handshake(); ws.accept(); @@ -942,8 +942,8 @@ public: // chopped control frame payload { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.next_layer().append( @@ -958,11 +958,11 @@ public: BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(to_string(b.data()) == "**"); }); - ios.run_one(); + ioc.run_one(); es.stream().write_some( boost::asio::buffer( "*" "\x81\x02**")); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 1); } @@ -981,11 +981,11 @@ public: }; char buf[32]; - stream ws{ios_}; + stream ws{ioc_}; stream::read_some_op< - boost::asio::mutable_buffers_1, + boost::asio::mutable_buffer, handler> op{handler{}, ws, - boost::asio::mutable_buffers_1{ + boost::asio::mutable_buffer{ buf, sizeof(buf)}}; using boost::asio::asio_handler_is_continuation; asio_handler_is_continuation(&op); @@ -998,7 +998,7 @@ public: }; multi_buffer b; - stream ws{ios_}; + stream ws{ioc_}; stream::read_op< multi_buffer, handler> op{ handler{}, ws, b, 32, true}; @@ -1014,8 +1014,8 @@ public: for(std::size_t i = 0; i < 100; ++i) { echo_server es{log, kind::async}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // too-big message frame indicates payload of 2^64-1 @@ -1033,14 +1033,14 @@ public: testIssue807() { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.write(sbuf("Hello, world!")); char buf[4]; - boost::asio::mutable_buffers_1 cb{buf, 0}; - auto const n = ws.read_some(cb); + boost::asio::mutable_buffer b{buf, 0}; + auto const n = ws.read_some(b); BEAST_EXPECT(n == 0); } diff --git a/test/beast/websocket/stream.cpp b/test/beast/websocket/stream.cpp index 17132b64..1367b567 100644 --- a/test/beast/websocket/stream.cpp +++ b/test/beast/websocket/stream.cpp @@ -22,7 +22,7 @@ public: void testOptions() { - stream ws{ios_}; + stream ws{ioc_}; ws.auto_fragment(true); ws.write_buffer_size(2048); ws.binary(false); @@ -40,7 +40,7 @@ public: auto const bad = [&](permessage_deflate const& pmd) { - stream ws{ios_}; + stream ws{ioc_}; try { ws.set_option(pmd); @@ -105,7 +105,7 @@ public: run() override { BOOST_STATIC_ASSERT(std::is_constructible< - stream, boost::asio::io_service&>::value); + stream, boost::asio::io_context&>::value); BOOST_STATIC_ASSERT(std::is_move_constructible< stream>::value); diff --git a/test/beast/websocket/test.hpp b/test/beast/websocket/test.hpp index fb9f0794..739657eb 100644 --- a/test/beast/websocket/test.hpp +++ b/test/beast/websocket/test.hpp @@ -10,12 +10,14 @@ #ifndef BEAST_TEST_WEBSOCKET_TEST_HPP #define BEAST_TEST_WEBSOCKET_TEST_HPP +#include #include #include #include #include #include #include +#include #include #include #include @@ -51,9 +53,10 @@ public: }; std::ostream& log_; - boost::asio::io_service ios_; + boost::asio::io_context ioc_; boost::optional< - boost::asio::io_service::work> work_; + boost::asio::executor_work_guard< + boost::asio::io_context::executor_type>> work_; static_buffer buffer_; test::stream ts_; std::thread t_; @@ -66,8 +69,8 @@ public: std::ostream& log, kind k = kind::sync) : log_(log) - , work_(ios_) - , ts_(ios_) + , work_(ioc_.get_executor()) + , ts_(ioc_) , ws_(ts_) { permessage_deflate pmd; @@ -83,12 +86,12 @@ public: break; case kind::async: - t_ = std::thread{[&]{ ios_.run(); }}; + t_ = std::thread{[&]{ ioc_.run(); }}; do_accept(); break; case kind::async_client: - t_ = std::thread{[&]{ ios_.run(); }}; + t_ = std::thread{[&]{ ioc_.run(); }}; break; } } @@ -118,7 +121,7 @@ public: void async_close() { - ios_.post( + boost::asio::post(ioc_, [&] { if(ws_.is_open()) @@ -293,7 +296,7 @@ public: doFailLoop( [&](test::fail_counter& fc) { - test::stream ts{ios_, fc}; + test::stream ts{ioc_, fc}; f(ts); ts.close(); } @@ -316,7 +319,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc{n}; - test::stream ts{ios_, fc}; + test::stream ts{ioc_, fc}; ws_type ws{ts}; ws.set_option(pmd); @@ -363,13 +366,12 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append( + reinterpret_cast(b.data()), + b.size()); return s; } @@ -413,10 +415,10 @@ public: template static - boost::asio::const_buffers_1 + boost::asio::const_buffer sbuf(const char (&s)[N]) { - return boost::asio::const_buffers_1(&s[0], N-1); + return boost::asio::const_buffer(&s[0], N-1); } template< @@ -436,14 +438,14 @@ public: template bool - run_until(boost::asio::io_service& ios, + run_until(boost::asio::io_context& ioc, std::size_t limit, Pred&& pred) { for(std::size_t i = 0; i < limit; ++i) { if(pred()) return true; - ios.run_one(); + ioc.run_one(); } return false; } @@ -451,9 +453,9 @@ public: template bool run_until( - boost::asio::io_service& ios, Pred&& pred) + boost::asio::io_context& ioc, Pred&& pred) { - return run_until(ios, 100, pred); + return run_until(ioc, 100, pred); } inline diff --git a/test/beast/websocket/utf8_checker.cpp b/test/beast/websocket/utf8_checker.cpp index 3e94f4ce..45394e57 100644 --- a/test/beast/websocket/utf8_checker.cpp +++ b/test/beast/websocket/utf8_checker.cpp @@ -230,7 +230,7 @@ public: void testFourByteSequence() { - using boost::asio::const_buffers_1; + using boost::asio::const_buffer; utf8_checker utf8; std::uint8_t buf[4]; for(auto i = 240; i <= 244; ++i) @@ -364,7 +364,6 @@ public: void testWithStreamBuffer() { - using namespace boost::asio; { // Valid UTF8 encoded text std::vector> const data{{ @@ -395,13 +394,14 @@ public: static std::size_t constexpr size = 3; std::size_t n = s.size(); buffers_suffix< - boost::asio::const_buffers_1> cb{ - boost::asio::const_buffers_1(s.data(), n)}; + boost::asio::const_buffer> cb{ + boost::asio::const_buffer(s.data(), n)}; multi_buffer b; while(n) { auto const amount = (std::min)(n, size); - b.commit(buffer_copy(b.prepare(amount), cb)); + b.commit(boost::asio::buffer_copy( + b.prepare(amount), cb)); cb.consume(amount); n -= amount; } diff --git a/test/beast/websocket/write.cpp b/test/beast/websocket/write.cpp index d45f9f84..afa52700 100644 --- a/test/beast/websocket/write.cpp +++ b/test/beast/websocket/write.cpp @@ -32,7 +32,7 @@ public: // already closed { echo_server es{log}; - stream ws{ios_}; + stream ws{ioc_}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); ws.close({}); @@ -255,8 +255,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -280,7 +280,7 @@ public: BEAST_EXPECT(n == 1); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -288,8 +288,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -312,7 +312,7 @@ public: system_error{ec}); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -320,8 +320,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); // add a ping and message to the input @@ -339,8 +339,8 @@ public: }); while(! ws.wr_block_) { - ios.run_one(); - if(! BEAST_EXPECT(! ios.stopped())) + ioc.run_one(); + if(! BEAST_EXPECT(! ioc.stopped())) break; } BEAST_EXPECT(count == 0); @@ -354,7 +354,7 @@ public: BEAST_EXPECT(n == 1); }); BEAST_EXPECT(count == 0); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -362,8 +362,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log, kind::async_client}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); es.async_handshake(); ws.accept(); @@ -388,7 +388,7 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -396,8 +396,8 @@ public: doFailLoop([&](test::fail_counter& fc) { echo_server es{log, kind::async_client}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); es.async_handshake(); ws.accept(); @@ -422,7 +422,7 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); BEAST_EXPECT(count == 2); }); @@ -431,8 +431,8 @@ public: { echo_server es{log}; error_code ec; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -456,7 +456,7 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); }); // suspend on ping: mask, frag @@ -464,8 +464,8 @@ public: { echo_server es{log}; error_code ec; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; ws.next_layer().connect(es.stream()); ws.handshake("localhost", "/"); std::size_t count = 0; @@ -489,15 +489,15 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); }); // suspend on ping: deflate doFailLoop([&](test::fail_counter& fc) { echo_server es{log, kind::async}; - boost::asio::io_service ios; - stream ws{ios, fc}; + boost::asio::io_context ioc; + stream ws{ioc, fc}; { permessage_deflate pmd; pmd.client_enable = true; @@ -527,7 +527,7 @@ public: BOOST_THROW_EXCEPTION( system_error{ec}); }); - ios.run(); + ioc.run(); }); } @@ -540,8 +540,8 @@ public: { echo_server es{log, i==1 ? kind::async : kind::sync}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); error_code ec; @@ -557,7 +557,7 @@ public: if(! BEAST_EXPECTS(! ec, ec.message())) break; // - // Destruction of the io_service will cause destruction + // Destruction of the io_context will cause destruction // of the write_some_op without invoking the final handler. // break; @@ -577,8 +577,8 @@ public: { echo_server es{log, i==1 ? kind::async : kind::sync}; - boost::asio::io_service ios; - stream ws{ios}; + boost::asio::io_context ioc; + stream ws{ioc}; ws.next_layer().connect(es.stream()); error_code ec; @@ -602,11 +602,11 @@ public: }; char buf[32]; - stream ws{ios_}; + stream ws{ioc_}; stream::write_some_op< - boost::asio::const_buffers_1, + boost::asio::const_buffer, handler> op{handler{}, ws, true, - boost::asio::const_buffers_1{ + boost::asio::const_buffer{ buf, sizeof(buf)}}; using boost::asio::asio_handler_is_continuation; asio_handler_is_continuation(&op); diff --git a/test/bench/buffers/bench_buffers.cpp b/test/bench/buffers/bench_buffers.cpp index d656f1ce..c6abd05a 100644 --- a/test/bench/buffers/bench_buffers.cpp +++ b/test/bench/buffers/bench_buffers.cpp @@ -67,15 +67,13 @@ public: fill(MutableBufferSequence const& buffers) { std::size_t n = 0; - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - for(boost::asio::mutable_buffer buffer : buffers) + for(auto b : beast::detail::buffers_range(buffers)) { std::fill( - buffer_cast(buffer), - buffer_cast(buffer) + - buffer_size(buffer), '\0'); - n += buffer_size(buffer); + reinterpret_cast(b.data()), + reinterpret_cast(b.data()) + + b.size(), '\0'); + n += b.size(); } return n; } diff --git a/test/bench/parser/bench_parser.cpp b/test/bench/parser/bench_parser.cpp index 659fe3f1..3b4a8327 100644 --- a/test/bench/parser/bench_parser.cpp +++ b/test/bench/parser/bench_parser.cpp @@ -42,13 +42,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast(b.data()), + b.size()); return s; } @@ -172,7 +170,7 @@ public: isRequest, bench_parser> { using mutable_buffers_type = - boost::asio::mutable_buffers_1; + boost::asio::mutable_buffer; void on_request_impl(verb, string_view, diff --git a/test/bench/parser/nodejs_parser.hpp b/test/bench/parser/nodejs_parser.hpp index 2d5a7e73..ada007f0 100644 --- a/test/bench/parser/nodejs_parser.hpp +++ b/test/bench/parser/nodejs_parser.hpp @@ -264,17 +264,15 @@ std::size_t nodejs_basic_parser::write( ConstBufferSequence const& buffers, error_code& ec) { - static_assert(beast::is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::size_t bytes_used = 0; - for(boost::asio::const_buffer buffer : buffers) + for(auto buffer : beast::detail::buffers_range(buffers)) { auto const n = write( - buffer_cast(buffer), - buffer_size(buffer), ec); + reinterpret_cast(buffer.data()), + buffer.size(), ec); if(ec) return 0; bytes_used += n; diff --git a/test/bench/wsload/wsload.cpp b/test/bench/wsload/wsload.cpp index 58f7deaf..34c475ba 100644 --- a/test/bench/wsload/wsload.cpp +++ b/test/bench/wsload/wsload.cpp @@ -39,19 +39,37 @@ namespace ws = boost::beast::websocket; namespace ph = std::placeholders; using error_code = boost::beast::error_code; -class test_buffer : public asio::const_buffers_1 +class test_buffer { char data_[4096]; + boost::asio::const_buffer b_; public: + using const_iterator = + boost::asio::const_buffer const*; + + using value_type = boost::asio::const_buffer; + test_buffer() - : asio::const_buffers_1(data_, sizeof(data_)) + : b_(data_, sizeof(data_)) { std::mt19937_64 rng; std::uniform_int_distribution dist; for(auto& c : data_) c = static_cast(dist(rng)); } + + const_iterator + begin() const + { + return &b_; + } + + const_iterator + end() const + { + return begin() + 1; + } }; class report @@ -96,7 +114,8 @@ class connection std::size_t messages_; report& rep_; test_buffer const& tb_; - asio::io_service::strand strand_; + asio::strand< + asio::io_context::executor_type> strand_; boost::beast::multi_buffer buffer_; std::mt19937_64 rng_; std::size_t count_ = 0; @@ -105,18 +124,18 @@ class connection public: connection( - asio::io_service& ios, + asio::io_context& ioc, tcp::endpoint const& ep, std::size_t messages, bool deflate, report& rep, test_buffer const& tb) - : ws_(ios) + : ws_(ioc) , ep_(ep) , messages_(messages) , rep_(rep) , tb_(tb) - , strand_(ios) + , strand_(ioc.get_executor()) { ws::permessage_deflate pmd; pmd.client_enable = deflate; @@ -274,7 +293,7 @@ main(int argc, char** argv) return EXIT_FAILURE; } - auto const address = ip::address::from_string(argv[1]); + auto const address = boost::asio::ip::make_address(argv[1]); auto const port = static_cast(std::atoi(argv[2])); auto const trials = static_cast(std::atoi(argv[3])); auto const messages= static_cast(std::atoi(argv[4])); @@ -286,12 +305,12 @@ main(int argc, char** argv) for(auto i = trials; i != 0; --i) { report rep; - boost::asio::io_service ios{1}; + boost::asio::io_context ioc{1}; for(auto j = workers; j; --j) { auto sp = std::make_shared( - ios, + ioc, tcp::endpoint{address, port}, work, deflate, @@ -304,9 +323,9 @@ main(int argc, char** argv) if(threads > 1) { tv.reserve(threads); - tv.emplace_back([&ios]{ ios.run(); }); + tv.emplace_back([&ioc]{ ioc.run(); }); } - ios.run(); + ioc.run(); for(auto& t : tv) t.join(); auto const elapsed = clock.elapsed(); diff --git a/test/doc/core_examples.cpp b/test/doc/core_examples.cpp index af3fae91..65a985cc 100644 --- a/test/doc/core_examples.cpp +++ b/test/doc/core_examples.cpp @@ -50,7 +50,7 @@ public: testRead() { { - test::stream ts{ios_, "\x16***"}; + test::stream ts{ioc_, "\x16***"}; error_code ec; flat_buffer b; auto const result = detect_ssl(ts, b, ec); @@ -60,7 +60,7 @@ public: yield_to( [&](yield_context yield) { - test::stream ts{ios_, "\x16***"}; + test::stream ts{ioc_, "\x16***"}; error_code ec; flat_buffer b; auto const result = diff --git a/test/doc/core_snippets.cpp b/test/doc/core_snippets.cpp index 728971a8..cf8bb1ef 100644 --- a/test/doc/core_snippets.cpp +++ b/test/doc/core_snippets.cpp @@ -27,12 +27,12 @@ void fxx() // using namespace boost::beast; -boost::asio::io_service ios; -boost::asio::io_service::work work{ios}; -std::thread t{[&](){ ios.run(); }}; +boost::asio::io_context ioc; +auto work = boost::asio::make_work_guard(ioc); +std::thread t{[&](){ ioc.run(); }}; error_code ec; -boost::asio::ip::tcp::socket sock{ios}; +boost::asio::ip::tcp::socket sock{ioc}; //] @@ -40,9 +40,10 @@ boost::asio::ip::tcp::socket sock{ios}; //[snippet_core_2 char const* const host = "www.example.com"; -boost::asio::ip::tcp::resolver r{ios}; -boost::asio::ip::tcp::socket stream{ios}; -boost::asio::connect(stream, r.resolve({host, "http"})); +boost::asio::ip::tcp::resolver r{ioc}; +boost::asio::ip::tcp::socket stream{ioc}; +auto const results = r.resolve(host, "http"); +boost::asio::connect(stream, results.begin(), results.end()); // At this point `stream` is a connected to a remote // host and may be used to perform stream operations. @@ -59,7 +60,7 @@ void write_string(SyncWriteStream& stream, string_view s) { static_assert(is_sync_write_stream::value, "SyncWriteStream requirements not met"); - boost::asio::write(stream, boost::asio::const_buffers_1(s.data(), s.size())); + boost::asio::write(stream, boost::asio::const_buffer(s.data(), s.size())); } //] diff --git a/test/doc/exemplars.cpp b/test/doc/exemplars.cpp index 98d90ad8..e97d6852 100644 --- a/test/doc/exemplars.cpp +++ b/test/doc/exemplars.cpp @@ -53,7 +53,7 @@ struct BodyReader { public: /// The type of buffer returned by `get`. - using const_buffers_type = boost::asio::const_buffers_1; + using const_buffers_type = boost::asio::const_buffer; /** Construct the reader. diff --git a/test/doc/http_examples.cpp b/test/doc/http_examples.cpp index afee4b08..4aac72ad 100644 --- a/test/doc/http_examples.cpp +++ b/test/doc/http_examples.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -57,13 +58,11 @@ public: std::string to_string(ConstBufferSequence const& bs) { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; std::string s; s.reserve(buffer_size(bs)); - for(boost::asio::const_buffer b : bs) - s.append(buffer_cast(b), - buffer_size(b)); + for(auto b : beast::detail::buffers_range(bs)) + s.append(reinterpret_cast< + char const*>(b.data()), b.size()); return s; } @@ -71,7 +70,7 @@ public: bool equal_body(string_view sv, string_view body) { - test::stream ts{ios_, sv}; + test::stream ts{ioc_, sv}; message m; multi_buffer b; ts.close_remote(); @@ -90,7 +89,7 @@ public: void doExpect100Continue() { - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); yield_to( [&](yield_context) @@ -123,10 +122,10 @@ public: doCgiResponse() { std::string const s = "Hello, world!"; - test::stream t0{ios_, s}; + test::stream t0{ioc_, s}; t0.read_size(3); t0.close_remote(); - test::stream t1{ios_}, t1r{ios_}; + test::stream t1{ioc_}, t1r{ioc_}; t1.connect(t1r); error_code ec; send_cgi_response(t0, t1, ec); @@ -145,10 +144,10 @@ public: req.body() = "Hello, world!"; req.prepare_payload(); - test::stream ds{ios_}, dsr{ios_}; + test::stream ds{ioc_}, dsr{ioc_}; ds.connect(dsr); dsr.read_size(3); - test::stream us{ios_}, usr{ios_}; + test::stream us{ioc_}, usr{ioc_}; us.connect(usr); us.write_size(3); @@ -241,7 +240,7 @@ public: void doHEAD() { - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); yield_to( [&](yield_context) @@ -280,7 +279,7 @@ public: void doDeferredBody() { - test::stream ts(ios_, + test::stream ts(ioc_, "POST / HTTP/1.1\r\n" "User-Agent: test\r\n" "Content-Type: multipart/form-data\r\n" @@ -299,7 +298,7 @@ public: void doIncrementalRead() { - test::stream ts{ios_}; + test::stream ts{ioc_}; std::string s(2048, '*'); ostream(ts.buffer()) << "HTTP/1.1 200 OK\r\n" @@ -323,10 +322,10 @@ public: auto const buf = [](string_view s) { - return boost::asio::const_buffers_1{ + return boost::asio::const_buffer{ s.data(), s.size()}; }; - test::stream ts{ios_}, tr{ios_}; + test::stream ts{ioc_}, tr{ioc_}; ts.connect(tr); response res{status::ok, 11}; @@ -394,7 +393,7 @@ public: void doExplicitChunkParse() { - test::stream ts(ios_, + test::stream ts(ioc_, "HTTP/1.1 200 OK\r\n" "Server: test\r\n" "Trailer: Expires, Content-MD5\r\n" diff --git a/test/doc/http_snippets.cpp b/test/doc/http_snippets.cpp index d2ec807f..ad930c4a 100644 --- a/test/doc/http_snippets.cpp +++ b/test/doc/http_snippets.cpp @@ -26,20 +26,20 @@ namespace doc_http_snippets { //[http_snippet_17 // This function returns the buffer containing the next chunk body -boost::asio::const_buffers_1 get_next_chunk_body(); +boost::asio::const_buffer get_next_chunk_body(); //] -boost::asio::const_buffers_1 get_next_chunk_body() +boost::asio::const_buffer get_next_chunk_body() { return {nullptr, 0}; } void fxx() { - boost::asio::io_service ios; - boost::asio::io_service::work work{ios}; - std::thread t{[&](){ ios.run(); }}; - boost::asio::ip::tcp::socket sock{ios}; + boost::asio::io_context ioc; + auto work = boost::asio::make_work_guard(ioc); + std::thread t{[&](){ ioc.run(); }}; + boost::asio::ip::tcp::socket sock{ioc}; { //[http_snippet_2 @@ -270,7 +270,7 @@ void fxx() { "Content-MD5: f4a5c16584f03d90\r\n" "Expires: never\r\n" "\r\n"; - boost::asio::write(sock, make_chunk_last(boost::asio::const_buffers_1{ext.data(), ext.size()})); + boost::asio::write(sock, make_chunk_last(boost::asio::const_buffer{ext.data(), ext.size()})); //] } diff --git a/test/doc/websocket_snippets.cpp b/test/doc/websocket_snippets.cpp index 92d6a787..4b1cc1e4 100644 --- a/test/doc/websocket_snippets.cpp +++ b/test/doc/websocket_snippets.cpp @@ -27,15 +27,15 @@ namespace doc_ws_snippets { void fxx() { -boost::asio::io_service ios; -boost::asio::io_service::work work{ios}; -std::thread t{[&](){ ios.run(); }}; +boost::asio::io_context ioc; +auto work = boost::asio::make_work_guard(ioc); +std::thread t{[&](){ ioc.run(); }}; error_code ec; -boost::asio::ip::tcp::socket sock{ios}; +boost::asio::ip::tcp::socket sock{ioc}; { //[ws_snippet_2 - stream ws{ios}; + stream ws{ioc}; //] } @@ -58,22 +58,23 @@ boost::asio::ip::tcp::socket sock{ios}; { //[ws_snippet_6 std::string const host = "mywebapp.com"; - boost::asio::ip::tcp::resolver r{ios}; - stream ws{ios}; - boost::asio::connect(ws.next_layer(), r.resolve({host, "ws"})); + boost::asio::ip::tcp::resolver r{ioc}; + stream ws{ioc}; + auto const results = r.resolve(host, "ws"); + boost::asio::connect(ws.next_layer(), results.begin(), results.end()); //] } { //[ws_snippet_7 - boost::asio::ip::tcp::acceptor acceptor{ios}; - stream ws{acceptor.get_io_service()}; + boost::asio::ip::tcp::acceptor acceptor{ioc}; + stream ws{acceptor.get_executor().context()}; acceptor.accept(ws.next_layer()); //] } { - stream ws{ios}; + stream ws{ioc}; //[ws_snippet_8 ws.handshake("localhost", "/"); //] @@ -137,7 +138,7 @@ boost::asio::ip::tcp::socket sock{ios}; } { - stream ws{ios}; + stream ws{ioc}; //[ws_snippet_14 // Read into our buffer until we reach the end of the HTTP request. // No parsing takes place here, we are just accumulating data. @@ -149,7 +150,7 @@ boost::asio::ip::tcp::socket sock{ios}; //] } { - stream ws{ios}; + stream ws{ioc}; //[ws_snippet_15 multi_buffer buffer; ws.read(buffer); @@ -161,7 +162,7 @@ boost::asio::ip::tcp::socket sock{ios}; } { - stream ws{ios}; + stream ws{ioc}; //[ws_snippet_16 multi_buffer buffer; for(;;) @@ -187,7 +188,7 @@ boost::asio::ip::tcp::socket sock{ios}; } { - stream ws{ios}; + stream ws{ioc}; //[ws_snippet_17 auto cb = [](frame_type kind, string_view payload) @@ -325,16 +326,16 @@ namespace doc_wss_snippets { void fxx() { -boost::asio::io_service ios; -boost::asio::io_service::work work{ios}; -std::thread t{[&](){ ios.run(); }}; +boost::asio::io_context ioc; +auto work = boost::asio::make_work_guard(ioc); +std::thread t{[&](){ ioc.run(); }}; error_code ec; -boost::asio::ip::tcp::socket sock{ios}; +boost::asio::ip::tcp::socket sock{ioc}; { //[wss_snippet_2 boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23}; - stream> wss{ios, ctx}; + stream> wss{ioc, ctx}; //] } @@ -342,7 +343,7 @@ boost::asio::ip::tcp::socket sock{ios}; //[wss_snippet_3 boost::asio::ip::tcp::endpoint ep; boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23}; - stream> ws{ios, ctx}; + stream> ws{ioc, ctx}; // connect the underlying TCP/IP socket ws.next_layer().next_layer().connect(ep); diff --git a/test/example/common/CMakeLists.txt b/test/example/common/CMakeLists.txt index a581c306..dff2123e 100644 --- a/test/example/common/CMakeLists.txt +++ b/test/example/common/CMakeLists.txt @@ -22,6 +22,5 @@ add_executable (tests-example-common server_certificate.cpp session_alloc.cpp ssl_stream.cpp - write_msg.cpp main.cpp ) diff --git a/test/example/common/Jamfile b/test/example/common/Jamfile index d5e58c98..719deba0 100644 --- a/test/example/common/Jamfile +++ b/test/example/common/Jamfile @@ -13,7 +13,6 @@ local SOURCES = server_certificate.cpp session_alloc.cpp ssl_stream.cpp - write_msg.cpp ; local RUN_TESTS ; diff --git a/test/example/common/write_msg.cpp b/test/example/common/write_msg.cpp deleted file mode 100644 index e7b1bf30..00000000 --- a/test/example/common/write_msg.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -// Test that header file is self-contained. -#include "example/common/write_msg.hpp" - diff --git a/test/extras/include/boost/beast/test/sig_wait.hpp b/test/extras/include/boost/beast/test/sig_wait.hpp index cb2ded45..847dc95b 100644 --- a/test/extras/include/boost/beast/test/sig_wait.hpp +++ b/test/extras/include/boost/beast/test/sig_wait.hpp @@ -21,14 +21,14 @@ inline void sig_wait() { - boost::asio::io_service ios; + boost::asio::io_context ioc; boost::asio::signal_set signals( - ios, SIGINT, SIGTERM); + ioc, SIGINT, SIGTERM); signals.async_wait( [&](boost::system::error_code const&, int) { }); - ios.run(); + ioc.run(); } } // test diff --git a/test/extras/include/boost/beast/test/stream.hpp b/test/extras/include/boost/beast/test/stream.hpp index c1228228..3352b988 100644 --- a/test/extras/include/boost/beast/test/stream.hpp +++ b/test/extras/include/boost/beast/test/stream.hpp @@ -10,15 +10,17 @@ #ifndef BOOST_BEAST_TEST_STREAM_HPP #define BOOST_BEAST_TEST_STREAM_HPP -#include #include +#include #include #include #include #include #include +#include #include -#include +#include +#include #include #include #include @@ -68,7 +70,7 @@ class stream flat_buffer b; std::condition_variable cv; std::unique_ptr op; - boost::asio::io_service& ios; + boost::asio::io_context& ioc; status code = status::ok; fail_counter* fc = nullptr; std::size_t nread = 0; @@ -85,9 +87,9 @@ class stream explicit state( - boost::asio::io_service& ios_, + boost::asio::io_context& ioc_, fail_counter* fc_) - : ios(ios_) + : ioc(ioc_) , fc(fc_) { } @@ -139,7 +141,7 @@ public: stream(stream&& other) { auto in = std::make_shared( - other.in_->ios, other.in_->fc); + other.in_->ioc, other.in_->fc); in_ = std::move(other.in_); out_ = std::move(other.out_); other.in_ = in; @@ -150,7 +152,7 @@ public: operator=(stream&& other) { auto in = std::make_shared( - other.in_->ios, other.in_->fc); + other.in_->ioc, other.in_->fc); in_ = std::move(other.in_); out_ = std::move(other.out_); other.in_ = in; @@ -159,24 +161,24 @@ public: /// Constructor explicit - stream(boost::asio::io_service& ios) - : in_(std::make_shared(ios, nullptr)) + stream(boost::asio::io_context& ioc) + : in_(std::make_shared(ioc, nullptr)) { } /// Constructor stream( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, fail_counter& fc) - : in_(std::make_shared(ios, &fc)) + : in_(std::make_shared(ioc, &fc)) { } /// Constructor stream( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, string_view s) - : in_(std::make_shared(ios, nullptr)) + : in_(std::make_shared(ioc, nullptr)) { using boost::asio::buffer; using boost::asio::buffer_copy; @@ -187,10 +189,10 @@ public: /// Constructor stream( - boost::asio::io_service& ios, + boost::asio::io_context& ioc, fail_counter& fc, string_view s) - : in_(std::make_shared(ios, &fc)) + : in_(std::make_shared(ioc, &fc)) { using boost::asio::buffer; using boost::asio::buffer_copy; @@ -209,12 +211,16 @@ public: remote.out_ = in_; } - /// Return the `io_service` associated with the stream - boost::asio::io_service& - get_io_service() + /// The type of the executor associated with the object. + using executor_type = + boost::asio::io_context::executor_type; + + /// Return the executor associated with the object. + boost::asio::io_context::executor_type + get_executor() noexcept { - return in_->ios; - } + return in_->ioc.get_executor(); + }; /** Get a reference to the lowest layer @@ -269,11 +275,11 @@ public: string_view str() const { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return { - buffer_cast(*in_->b.data().begin()), - buffer_size(*in_->b.data().begin())}; + auto const bs = in_->b.data(); + if(boost::asio::buffer_size(bs) == 0) + return {}; + auto const b = buffers_front(bs); + return {reinterpret_cast(b.data()), b.size()}; } /// Appends a string to the pending input data @@ -336,8 +342,8 @@ public: error_code& ec); template - async_return_type< - ReadHandler, void(error_code, std::size_t)> + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler); @@ -351,8 +357,8 @@ public: ConstBufferSequence const& buffers, error_code&); template - async_return_type< - WriteHandler, void(error_code, std::size_t)> + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler); @@ -405,7 +411,7 @@ std::size_t stream:: read_some(MutableBufferSequence const& buffers) { - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); error_code ec; @@ -421,7 +427,7 @@ stream:: read_some(MutableBufferSequence const& buffers, error_code& ec) { - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); using boost::asio::buffer_copy; @@ -460,27 +466,31 @@ read_some(MutableBufferSequence const& buffers, } template -async_return_type< - ReadHandler, void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(error_code, std::size_t)) stream:: async_read_some( MutableBufferSequence const& buffers, ReadHandler&& handler) { - static_assert(is_mutable_buffer_sequence< + static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); using boost::asio::buffer_copy; using boost::asio::buffer_size; BOOST_ASSERT(buffer_size(buffers) > 0); - async_completion init{handler}; if(in_->fc) { error_code ec; if(in_->fc->fail(ec)) - return in_->ios.post(bind_handler( - init.completion_handler, ec, 0)); + return boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + ec, + 0)); } { std::unique_lock lock{in_->m}; @@ -493,8 +503,12 @@ async_read_some( in_->b.consume(bytes_transferred); lock.unlock(); ++in_->nread; - in_->ios.post(bind_handler(init.completion_handler, - error_code{}, bytes_transferred)); + boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + error_code{}, + bytes_transferred)); } else if(in_->code != status::ok) { @@ -505,15 +519,19 @@ async_read_some( ec = boost::asio::error::eof; else if(in_->code == status::reset) ec = boost::asio::error::connection_reset; - in_->ios.post(bind_handler( - init.completion_handler, ec, 0)); + boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + ec, + 0)); } else { - in_->op.reset(new read_op_impl, - MutableBufferSequence>{*in_, buffers, - init.completion_handler}); + in_->op.reset(new read_op_impl{*in_, buffers, + init.completion_handler}); } } return init.result.get(); @@ -524,7 +542,7 @@ std::size_t stream:: write_some(ConstBufferSequence const& buffers) { - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); error_code ec; @@ -541,7 +559,7 @@ stream:: write_some( ConstBufferSequence const& buffers, error_code& ec) { - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; @@ -569,31 +587,38 @@ write_some( } template -async_return_type< - WriteHandler, void(error_code, std::size_t)> +BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(error_code, std::size_t)) stream:: async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler) { - static_assert(is_const_buffer_sequence< + static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; using boost::asio::buffer_size; - async_completion init{handler}; auto out = out_.lock(); if(! out) - return in_->ios.post( - bind_handler(init.completion_handler, - boost::asio::error::connection_reset, 0)); + return boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + boost::asio::error::connection_reset, + 0)); BOOST_ASSERT(out->code == status::ok); if(in_->fc) { error_code ec; if(in_->fc->fail(ec)) - return in_->ios.post(bind_handler( - init.completion_handler, ec, 0)); + return boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + ec, + 0)); } auto const n = (std::min)(buffer_size(buffers), in_->write_max); @@ -604,8 +629,12 @@ async_write_some(ConstBufferSequence const& buffers, out->on_write(); lock.unlock(); ++in_->nwrite; - in_->ios.post(bind_handler(init.completion_handler, - error_code{}, bytes_transferred)); + boost::asio::post( + in_->ioc.get_executor(), + bind_handler( + init.completion_handler, + error_code{}, + bytes_transferred)); return init.result.get(); } @@ -640,7 +669,8 @@ async_teardown( error_code ec; if( s.in_->fc && s.in_->fc->fail(ec)) - return s.get_io_service().post( + return boost::asio::post( + s.get_executor(), bind_handler(std::move(handler), ec)); s.close(); if( s.in_->fc && @@ -649,7 +679,8 @@ async_teardown( else ec.assign(0, ec.category()); - s.get_io_service().post( + boost::asio::post( + s.get_executor(), bind_handler(std::move(handler), ec)); } @@ -664,7 +695,8 @@ class stream::read_op_impl : public stream::read_op Buffers b_; Handler h_; boost::optional< - boost::asio::io_service::work> work_; + boost::asio::executor_work_guard< + boost::asio::io_context::executor_type>> work_; public: lambda(lambda&&) = default; @@ -674,7 +706,7 @@ class stream::read_op_impl : public stream::read_op : s_(s) , b_(b) , h_(std::move(h)) - , work_(s_.ios) + , work_(s_.ioc.get_executor()) { } @@ -682,14 +714,16 @@ class stream::read_op_impl : public stream::read_op : s_(s) , b_(b) , h_(h) - , work_(s_.ios) + , work_(s_.ioc.get_executor()) { } void post() { - s_.ios.post(std::move(*this)); + boost::asio::post( + s_.ioc.get_executor(), + std::move(*this)); work_ = boost::none; } @@ -709,8 +743,12 @@ class stream::read_op_impl : public stream::read_op Handler h{std::move(h_)}; lock.unlock(); ++s.nread; - s.ios.post(bind_handler(std::move(h), - error_code{}, bytes_transferred)); + boost::asio::post( + s.ioc.get_executor(), + bind_handler( + std::move(h), + error_code{}, + bytes_transferred)); } else { @@ -724,7 +762,9 @@ class stream::read_op_impl : public stream::read_op ec = boost::asio::error::eof; else if(s.code == status::reset) ec = boost::asio::error::connection_reset; - s.ios.post(bind_handler(std::move(h), ec, 0)); + boost::asio::post( + s.ioc.get_executor(), + bind_handler(std::move(h), ec, 0)); } } }; @@ -754,7 +794,7 @@ inline stream connect(stream& to) { - stream from{to.get_io_service()}; + stream from{to.get_executor().context()}; from.connect(to); return from; } diff --git a/test/extras/include/boost/beast/test/yield_to.hpp b/test/extras/include/boost/beast/test/yield_to.hpp index b7fb87ce..1fb3738f 100644 --- a/test/extras/include/boost/beast/test/yield_to.hpp +++ b/test/extras/include/boost/beast/test/yield_to.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_BEAST_TEST_YIELD_TO_HPP #define BOOST_BEAST_TEST_YIELD_TO_HPP -#include +#include #include #include #include @@ -32,10 +32,12 @@ namespace test { class enable_yield_to { protected: - boost::asio::io_service ios_; + boost::asio::io_context ioc_; private: - boost::optional work_; + boost::optional< + boost::asio::executor_work_guard< + boost::asio::io_context::executor_type>> work_; std::vector threads_; std::mutex m_; std::condition_variable cv_; @@ -48,12 +50,12 @@ public: explicit enable_yield_to(std::size_t concurrency = 1) - : work_(ios_) + : work_(ioc_.get_executor()) { threads_.reserve(concurrency); while(concurrency--) threads_.emplace_back( - [&]{ ios_.run(); }); + [&]{ ioc_.run(); }); } ~enable_yield_to() @@ -63,11 +65,11 @@ public: t.join(); } - /// Return the `io_service` associated with the object - boost::asio::io_service& + /// Return the `io_context` associated with the object + boost::asio::io_context& get_io_service() { - return ios_; + return ioc_; } /** Run one or more functions, each in a coroutine. @@ -119,7 +121,7 @@ void enable_yield_to:: spawn(F0&& f, FN&&... fn) { - boost::asio::spawn(ios_, + boost::asio::spawn(ioc_, [&](yield_context yield) { f(yield);