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
This commit is contained in:
Vinnie Falco
2017-10-23 17:11:27 -07:00
parent 9dc9ca13b9
commit 3a28e999af
173 changed files with 3214 additions and 4138 deletions
@@ -21,6 +21,7 @@
#include <boost/beast/http.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/strand.hpp>
@@ -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<Body, http::basic_fields<Allocator>> 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<plain_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<ssl_websocket_session>
{
websocket::stream<ssl_stream<tcp::socket>> 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<tcp::socket> stream)
: websocket_session<ssl_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<plain_http_session>
{
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<plain_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_http_session>
{
ssl_stream<tcp::socket> 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<ssl_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<detect_session>
{
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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
+70 -53
View File
@@ -17,6 +17,7 @@
#include <boost/beast/http.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/steady_timer.hpp>
@@ -214,7 +215,8 @@ fail(boost::system::error_code ec, char const* what)
class websocket_session : public std::enable_shared_from_this<websocket_session>
{
websocket::stream<tcp::socket> 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_session>
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<http_session>
};
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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
+51 -44
View File
@@ -61,7 +61,8 @@ is_ssl_handshake(
ConstBufferSequence const& buffers)
{
// Make sure buffers meets the requirements
static_assert(boost::beast::is_const_buffer_sequence<ConstBufferSequence>::value,
static_assert(
boost::asio::is_const_buffer_sequence<ConstBufferSequence>::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<SyncReadStream>::value,
"SyncReadStream requirements not met");
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::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<AsyncReadStream>::value,
"SyncReadStream requirements not met");
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::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<AsyncReadStream, DynamicBuffer, beast::handler_type<
CompletionToken, void(beast::error_code, boost::tribool)>>{
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<error_code, boost::tribool> 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<Handler>;
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<class Function>
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));
}
+239 -270
View File
@@ -10,21 +10,21 @@
#ifndef BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
#define BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
#include <boost/assert.hpp>
#include <boost/intrusive/list.hpp>
#include <algorithm>
#include <cstddef>
#include <utility>
namespace detail {
template<class Context>
class session_alloc_base
{
template<class Handler>
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<Context, std::nullptr_t>::value,
"Context requirements not met");
}
session_alloc_base(session_alloc_base const& other)
: pool_(other.pool_.addref())
{
}
template<class DeducedContext, class = typename
std::enable_if<! std::is_same<
session_alloc_base<Context>,
typename std::decay<DeducedContext>::type
>::value>::type>
explicit
session_alloc_base(DeducedContext& ctx)
: pool_(pool_t::construct(std::addressof(ctx)))
{
static_assert(! std::is_same<Context, std::nullptr_t>::value,
"Context requirements not met");
}
template<class Handler>
wrapped_handler<typename std::decay<Handler>::type>
wrap(Handler&& handler)
{
return wrapped_handler<
typename std::decay<Handler>::type>(
std::forward<Handler>(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<class Context>
auto
session_alloc_base<Context>::
pool_t::
construct() ->
pool_t&
{
return *(new pool_t);
}
template<class Context>
session_alloc_base<Context>::
pool_t::
~pool_t()
{
BOOST_ASSERT(list_.size() == 0);
if(buf_)
delete[] buf_;
}
template<class Context>
auto
session_alloc_base<Context>::
pool_t::
addref() ->
pool_t&
{
++refs_;
return *this;
}
template<class Context>
void
session_alloc_base<Context>::
pool_t::
release()
{
if(--refs_)
return;
delete this;
}
template<class Context>
void*
session_alloc_base<Context>::
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<class Context>
void
session_alloc_base<Context>::
pool_t::
dealloc(void* pv, std::size_t n)
{
auto& e = *(reinterpret_cast<element*>(pv) - 1);
BOOST_ASSERT(e.size() == n);
if( (e.end() > buf_ + size_) ||
reinterpret_cast<char*>(&e) < buf_)
{
list_.erase(list_.iterator_to(e));
e.~element();
delete[] reinterpret_cast<char*>(&e);
return;
}
list_.erase(list_.iterator_to(e));
e.~element();
}
} // detail
//------------------------------------------------------------------------------
template<class T, class Context = std::nullptr_t>
class session_alloc : public session_alloc_base<Context>
template<class T>
class session_alloc
: private detail::session_alloc_base<void>
{
template<class U, class C>
template<class U>
friend class session_alloc;
template<class Handler>
class wrapped_handler
{
// Can't friend partial specializations,
// so we just friend the whole thing.
template<class T, class Executor>
friend struct boost::asio::associated_executor;
Handler h_;
session_alloc<char> alloc_;
public:
wrapped_handler(wrapped_handler&&) = default;
wrapped_handler(wrapped_handler const&) = default;
template<class DeducedHandler>
wrapped_handler(
DeducedHandler&& h,
session_alloc const& alloc)
: h_(std::forward<DeducedHandler>(h))
, alloc_(alloc)
{
}
using allocator_type = session_alloc<char>;
allocator_type
get_allocator() const noexcept;
template<class... Args>
void
operator()(Args&&... args) const
{
h_(std::forward<Args>(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<void>::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<U>;
};
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<class U>
session_alloc(session_alloc<U> const& other)
: session_alloc_base<Context>(static_cast<
session_alloc_base<Context> const&>(other))
session_alloc(session_alloc<U> const& other) noexcept
: pool_(other.pool_)
{
}
explicit
session_alloc(Context& ctx)
: session_alloc_base<Context>(ctx)
{
}
template<class Handler>
wrapped_handler<typename std::decay<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<class Context>
template<class T>
template<class Handler>
class session_alloc_base<Context>::wrapped_handler
auto
session_alloc<T>::
wrapped_handler<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<class DeducedHandler>
explicit
wrapped_handler(DeducedHandler&& h,
session_alloc_base const& alloc)
: h_(std::forward<DeducedHandler>(h))
, alloc_(alloc)
{
}
template<class... Args>
void
operator()(Args&&... args) const
{
h_(std::forward<Args>(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<class F>
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<class Context>
template<class T>
template<class Handler>
auto
session_alloc_base<Context>::
pool_t::
construct(Context* ctx) ->
pool_t&
session_alloc<T>::
wrap(Handler&& handler) ->
wrapped_handler<typename std::decay<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<Handler>::type>(
std::forward<Handler>(handler), *this);
}
template<class Context>
session_alloc_base<Context>::
pool_t::
~pool_t()
namespace boost {
namespace asio {
template<class T, class Handler, class Executor>
struct associated_executor<
session_alloc<T>::wrapped_handler<Handler>, Executor>
{
BOOST_ASSERT(list_.size() == 0);
if(buf_)
using type = typename
associated_executor<Handler, Executor>::type;
static
type
get(session_alloc<T>::wrapped_handler<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<class Context>
auto
session_alloc_base<Context>::
pool_t::
addref() ->
pool_t&
{
++refs_;
return *this;
}
template<class Context>
void
session_alloc_base<Context>::
pool_t::
release()
{
if(--refs_)
return;
this->~pool_t();
using boost::asio::asio_handler_deallocate;
asio_handler_deallocate(this, sizeof(*this), ctx_);
}
template<class Context>
void*
session_alloc_base<Context>::
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<char*>(
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<class Context>
void
session_alloc_base<Context>::
pool_t::
dealloc(void* pv, std::size_t n)
{
auto& e = *(reinterpret_cast<element*>(pv) - 1);
BOOST_ASSERT(e.size() == n);
if( (e.end() > buf_ + size_) ||
reinterpret_cast<char*>(&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
+9 -16
View File
@@ -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<stream_type> p(
new stream_type{other.get_io_service(), other.ctx_});
std::unique_ptr<stream_type> 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
{
-230
View File
@@ -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 <boost/beast/core/async_result.hpp>
#include <boost/beast/core/handler_ptr.hpp>
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/write.hpp>
#include <boost/beast/http/type_traits.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
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<isRequest, Body, Fields> msg;
// Serializer for the message
boost::beast::http::serializer<isRequest, Body, Fields> sr;
data(
Handler& handler,
AsyncWriteStream& stream_,
boost::beast::http::message<isRequest, Body, Fields>&& 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<data, Handler> 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<DeducedHandler>(h),
s, std::forward<Args>(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<class Function>
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 <em>composed operation</em>.
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<WriteHandler, void(boost::beast::error_code)>
async_write_msg(
AsyncWriteStream& stream,
boost::beast::http::message<isRequest, Body, Fields>&& msg,
WriteHandler&& handler)
{
static_assert(
boost::beast::is_async_write_stream<AsyncWriteStream>::value,
"AsyncWriteStream requirements not met");
static_assert(boost::beast::http::is_body<Body>::value,
"Body requirements not met");
static_assert(boost::beast::http::is_body_reader<Body>::value,
"BodyReader requirements not met");
boost::beast::async_completion<WriteHandler, void(boost::beast::error_code)> init{handler};
::detail::write_msg_op<
AsyncWriteStream,
boost::beast::handler_type<WriteHandler, void(boost::beast::error_code)>,
isRequest, Body, Fields>{
init.completion_handler,
stream,
std::move(msg)}();
return init.result.get();
}
#endif
+16 -21
View File
@@ -62,7 +62,8 @@ send_expect_100_continue(
static_assert(is_sync_stream<SyncStream>::value,
"SyncStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
// Insert or replace the Expect field
@@ -123,7 +124,8 @@ receive_expect_100_continue(
static_assert(is_sync_stream<SyncStream>::value,
"SyncStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::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<SyncWriteStream>::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<buffer_body> res;
@@ -293,7 +292,8 @@ void do_server_head(
{
static_assert(is_sync_stream<SyncStream>::value,
"SyncStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::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<SyncStream>::value,
"SyncStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
static_assert(
boost::asio::is_dynamic_buffer<DynamicBuffer>::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<char const*>(buffer),
buffer_size(buffer));
reinterpret_cast<char const*>(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<std::size_t>(is.rdbuf()->in_avail()));
// Now get everything we can from the istream
buffer.commit(static_cast<std::size_t>(is.readsome(
boost::asio::buffer_cast<char*>(mb),
boost::asio::buffer_size(mb))));
reinterpret_cast<char*>(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<char*>(mb),
boost::asio::buffer_size(mb));
is.read(reinterpret_cast<char*>(b.data()), b.size());
// If an error occurs on the istream then return it to the caller.
if(is.fail() && ! is.eof())
+61 -83
View File
@@ -23,7 +23,7 @@ auto
async_echo(AsyncStream& stream, CompletionToken&& token)
//]
-> boost::beast::async_return_type<CompletionToken, void(boost::beast::error_code)>;
-> 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<boost::beast::handler_alloc<char, Handler>> buffer;
boost::asio::basic_streambuf<typename std::allocator_traits<
boost::asio::associated_allocator_t<Handler> >::
template rebind_alloc<char> > 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<std::size_t>::max)(),
boost::beast::handler_alloc<char, Handler>{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<state, Handler> 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<Handler>;
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<class AsyncStream_, class Handler_>
friend bool asio_handler_is_continuation(
echo_op<AsyncStream_, Handler_>* 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<class AsyncStream_, class Handler_, class Function>
friend void asio_handler_invoke(
Function&& f, echo_op<AsyncStream_, Handler_>* op);
template<class AsyncStream_, class Handler_>
friend void* asio_handler_allocate(
std::size_t size, echo_op<AsyncStream_, Handler_>* op);
template<class AsyncStream_, class Handler_>
friend void asio_handler_deallocate(
void* p, std::size_t size, echo_op<AsyncStream_, Handler_>* op);
template<class AsyncStream_, class Handler_>
friend bool asio_handler_is_continuation(
echo_op<AsyncStream_, Handler_>* 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<class AsyncStream, class Handler, class Function>
void asio_handler_invoke(
Function&& f, echo_op<AsyncStream, Handler>* op)
{
using boost::asio::asio_handler_invoke;
return asio_handler_invoke(f, std::addressof(op->p_.handler()));
}
template<class AsyncStream, class Handler>
void* asio_handler_allocate(
std::size_t size, echo_op<AsyncStream, Handler>* op)
{
using boost::asio::asio_handler_allocate;
return asio_handler_allocate(size, std::addressof(op->p_.handler()));
}
template<class AsyncStream, class Handler>
void asio_handler_deallocate(
void* p, std::size_t size, echo_op<AsyncStream, Handler>* 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<class AsyncStream, class CompletionToken>
boost::beast::async_return_type<CompletionToken, void(boost::beast::error_code)>
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<CompletionToken, void(boost::beast::error_code)> init{token};
boost::asio::async_completion<CompletionToken, void(boost::beast::error_code)> 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<AsyncStream, boost::beast::handler_type<CompletionToken, void(boost::beast::error_code)>>{
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<error_code> 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;
}
@@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
http::response<http::string_body> 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<session>(ios, ctx)->run(host, port, target);
std::make_shared<session>(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;
}
+16 -11
View File
@@ -46,11 +46,11 @@ class session : public std::enable_shared_from_this<session>
http::response<http::string_body> 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<session>(ios)->run(host, port, target);
std::make_shared<session>(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;
}
@@ -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<tcp::socket> stream{ios, ctx};
tcp::resolver resolver{ioc};
ssl::stream<tcp::socket> 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;
}
+10 -10
View File
@@ -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;
}
+89 -75
View File
@@ -18,10 +18,11 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/strand.hpp>
#include <boost/optional.hpp>
#include <atomic>
#include <chrono>
#include <cstdlib>
@@ -43,16 +44,17 @@ namespace chrono = std::chrono; // from <chrono>
// 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<std::size_t> index_;
std::vector<char const*> 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<worker>
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<http::empty_body> req_;
http::response<http::string_body> res_;
@@ -156,16 +160,16 @@ class worker : public std::enable_shared_from_this<worker>
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<std::size_t>(1, std::atoi(argv[1]));
auto const threads = std::max<int>(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<boost::asio::io_service::work> 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<std::thread> 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<worker>(report, ios)->run();
ios.run();
boost::asio::io_context ioc{1};
std::make_shared<worker>(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();
@@ -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<tcp::socket> stream{ios, ctx};
tcp::resolver resolver{ioc};
ssl::stream<tcp::socket> 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);
@@ -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<http::string_body> req{http::verb::get, target, 11};
@@ -18,6 +18,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/strand.hpp>
@@ -244,18 +245,21 @@ class session : public std::enable_shared_from_this<session>
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<tcp::socket&> 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<http::string_body> 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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
+31 -25
View File
@@ -16,6 +16,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/config.hpp>
@@ -240,17 +241,20 @@ class session : public std::enable_shared_from_this<session>
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<http::string_body> 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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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;
}
+14 -14
View File
@@ -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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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;
}
@@ -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<std::chrono::steady_clock> 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<http::response<http::string_body, http::basic_fields<alloc_t>>> 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<unsigned short>(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<http_worker> 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)
{
+66 -50
View File
@@ -19,6 +19,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/strand.hpp>
@@ -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<plain_session>
{
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<plain_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<tcp::socket&> 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<ssl_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<detect_session>
{
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<listener>
{
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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
@@ -75,7 +75,7 @@ private:
// The timer for putting a deadline on connection processing.
boost::asio::basic_waitable_timer<std::chrono::steady_clock> 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<unsigned short>(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)
{
@@ -18,6 +18,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
@@ -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<tcp::socket&> 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<http::string_body> 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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
@@ -16,6 +16,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
@@ -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<http::string_body> 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<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
auto const threads = std::max<int>(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<listener>(
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;
}
@@ -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<unsigned short>(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);
@@ -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<unsigned short>(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);
@@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
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<session>(ios, ctx)->run(host, port, text);
std::make_shared<session>(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;
}
@@ -45,11 +45,11 @@ class session : public std::enable_shared_from_this<session>
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<session>(ios)->run(host, port, text);
std::make_shared<session>(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;
}
@@ -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<ssl::stream<tcp::socket>> ws{ios, ctx};
tcp::resolver resolver{ioc};
websocket::stream<ssl::stream<tcp::socket>> 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;
}
@@ -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<tcp::socket> ws{ios};
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> 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;
}
@@ -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<ssl::stream<tcp::socket>> ws{ios, ctx};
tcp::resolver resolver{ioc};
websocket::stream<ssl::stream<tcp::socket>> 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);
@@ -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<tcp::socket> ws{ios};
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> 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, "/");
@@ -18,6 +18,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
@@ -48,7 +49,8 @@ class session : public std::enable_shared_from_this<session>
{
tcp::socket socket_;
websocket::stream<ssl::stream<tcp::socket&>> 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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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<listener>(ios, ctx, tcp::endpoint{address, port})->run();
std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> 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;
}
@@ -15,6 +15,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
@@ -42,7 +43,8 @@ fail(boost::system::error_code ec, char const* what)
class session : public std::enable_shared_from_this<session>
{
websocket::stream<tcp::socket> 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<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;
@@ -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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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<listener>(ios, tcp::endpoint{address, port})->run();
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> 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;
}
@@ -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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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;
}
@@ -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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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;
}
@@ -30,6 +30,7 @@
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -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<async_session>
{
websocket::stream<tcp::socket> 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<async_listener>
{
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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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<unsigned short>(port + 0u)}
@@ -428,16 +439,16 @@ int main(int argc, char* argv[])
// Create async port
std::make_shared<async_listener>(
ios,
ioc,
tcp::endpoint{
address,
static_cast<unsigned short>(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<unsigned short>(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;
}
@@ -18,6 +18,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
@@ -51,7 +52,8 @@ class session
{
tcp::socket socket_;
websocket::stream<ssl::stream<tcp::socket&>> 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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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<listener>(ios, ctx, tcp::endpoint{address, port})->run();
std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> 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;
}
@@ -15,6 +15,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -45,7 +46,8 @@ class session
, public std::enable_shared_from_this<session>
{
websocket::stream<tcp::socket> 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<unsigned short>(std::atoi(argv[2]));
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
auto const threads = std::max<int>(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<listener>(ios, tcp::endpoint{address, port})->run();
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> 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;
}
@@ -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<unsigned short>(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);
@@ -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<unsigned short>(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);