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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With