Reputation: 1409
I am trying boost::beast
examples, I came across to this piece of code.
void on_write(beast::error_code ec, std::size_t byte_transferred) {
if (ec) return fail(ec, "write");
http::async_read(m_tcp_stream, m_buffer, m_response, beast::bind_front_handler(
&Session::on_read, shared_from_this()));
}
void on_read(beast::error_code ec, std::size_t bytes_transferred) {
if (ec) return fail(ec, "read");
//std::cout << m_response << std::endl;
write_on_file(m_response);
m_tcp_stream.socket().shutdown(tcp::socket::shutdown_both, ec);
if (ec && ec != beast::errc::not_connected) return fail(ec, "showdown");
}
Particularly http::async_read(m_tcp_stream, m_buffer, m_response, beast::bind_front_handler(&Session::on_read, shared_from_this()));
this line. I am not able to understand its code. How does it work. As far as I get from the code, that It returns bind_front_wrapper
which constructs a Handler
and tuple of args
within itself. But I did not understand how does it manage to get the arguments of the passed Handler
in bind_front_handler
even though we are not passing, we are just passing shared_ptr
. In this case async_read
is calling on_read
method. But we are not passing any parameters, but still it get called, I wonder how?
Upvotes: 10
Views: 3994
Reputation: 20959
You use asynchronous operations, so your job is to define callbacks which are called
by Beast core code when operations are completed. When an operation started by async_read
is ready,
handler passed to async_read
is called with two arguments: error code + number of transferred bytes.
You decided to wrap on_read
into callback by bind_front_handler
. bind_front_handler
generates a functor object
whose implementation in pseudocode may look like:
class Handler {
void (Session::*onRead)(...); // pointer to on_read function member of Session
Session* session; // pointer to session, get by shared_from_this
Handler(/* pointer to on_read, pointer to session */) {}
template<class ... Args>
void operator() (Args... args) {
((*session).*onRead)(args...);
}
}
when read operation is ready, function operator()
of above handler is called with two arguments pack: error code
and number of read bytes.
Since c++20 there is std::bind_front
,
you may visit reference to get more details how it could be implemented in Beast library.
Upvotes: 4