Aarón Bueno Villares
2016-09-24 01:31:12 UTC
I've tried to make a "synchronous" recaptcha verification using the
underlaying Wt's IOService, asynchronous in nature. The code is the
following one:
// response_ready is just a std::condition_variable (I have tested with
boost:: as well
// for mutex, locks and the condition_variable and the result is the same).
void google_recaptcha::p_verify(std::string const& recaptcha_response)
{
auto* client = new Wt::Http::Client(this);
client->done().connect(this, &google_recaptcha::p_on_done);
std::ostringstream os;
os << "secret=" << st_server_secret << "&response=" <<
recaptcha_response;
Wt::Http::Message msg;
msg.addBodyText(os.str());
msg.setHeader("Content-Type", "application/x-www-form-urlencoded");
client->post("https://www.google.com/recaptcha/api/siteverify", msg);
std::unique_lock<std::mutex> lk(wait_mutex);
response_ready.wait_for(lk, std::chrono::seconds(15),
[this]() -> bool { return
b_is_done; });
}
void google_recaptcha::p_on_done(boost::system::error_code const& err,
Wt::Http::Message
const& response)
{
// Suppose everything works fine, to avoid dealing with exceptions
(temporarily).
std::cout << "IN SLOT" << std::endl;
std::stringstream ss(response.body());
boost::property_tree::ptree ptree;
boost::property_tree::read_json(ss, ptree);
auto success_optional = ptree.get_optional<bool>("success");
o_verified.emit(success_optional.get()); // o_verified is a Wt::Signal.
std::lock_guard<std::mutex> lk(wait_mutex);
b_is_done = true;
response_ready.notify_one();
}
And I don't know why, but when the JSignal is emitted (p_verified is
connected to a JSignal), the thread is blocked at the `wait_for` line, and,
after those 15 seconds of waiting, the `p_on_done` is method is called (it
prints "IN SLOT"). So, they are not executed concurrently. Could it be
because of the `strand` object which Wt's manages internally?
I don't know if the `post` request ends and the `p_on_done` slot is which
is waiting, or the `post` request is which waits. The thing is that it
seems Wt tries to dispatch the `p_on_done` slots in the same thread than
the `p_verify` slot's, so the block.
How can I force `p_on_done` is executed concurrently? I'm interested in
knowing both, the solution and why my approach is a blocking one.
underlaying Wt's IOService, asynchronous in nature. The code is the
following one:
// response_ready is just a std::condition_variable (I have tested with
boost:: as well
// for mutex, locks and the condition_variable and the result is the same).
void google_recaptcha::p_verify(std::string const& recaptcha_response)
{
auto* client = new Wt::Http::Client(this);
client->done().connect(this, &google_recaptcha::p_on_done);
std::ostringstream os;
os << "secret=" << st_server_secret << "&response=" <<
recaptcha_response;
Wt::Http::Message msg;
msg.addBodyText(os.str());
msg.setHeader("Content-Type", "application/x-www-form-urlencoded");
client->post("https://www.google.com/recaptcha/api/siteverify", msg);
std::unique_lock<std::mutex> lk(wait_mutex);
response_ready.wait_for(lk, std::chrono::seconds(15),
[this]() -> bool { return
b_is_done; });
}
void google_recaptcha::p_on_done(boost::system::error_code const& err,
Wt::Http::Message
const& response)
{
// Suppose everything works fine, to avoid dealing with exceptions
(temporarily).
std::cout << "IN SLOT" << std::endl;
std::stringstream ss(response.body());
boost::property_tree::ptree ptree;
boost::property_tree::read_json(ss, ptree);
auto success_optional = ptree.get_optional<bool>("success");
o_verified.emit(success_optional.get()); // o_verified is a Wt::Signal.
std::lock_guard<std::mutex> lk(wait_mutex);
b_is_done = true;
response_ready.notify_one();
}
And I don't know why, but when the JSignal is emitted (p_verified is
connected to a JSignal), the thread is blocked at the `wait_for` line, and,
after those 15 seconds of waiting, the `p_on_done` is method is called (it
prints "IN SLOT"). So, they are not executed concurrently. Could it be
because of the `strand` object which Wt's manages internally?
I don't know if the `post` request ends and the `p_on_done` slot is which
is waiting, or the `post` request is which waits. The thing is that it
seems Wt tries to dispatch the `p_on_done` slots in the same thread than
the `p_verify` slot's, so the block.
How can I force `p_on_done` is executed concurrently? I'm interested in
knowing both, the solution and why my approach is a blocking one.