The following C++ code fragment makes use of Microsoft's C++ Rest SDK. I'm not understanding why the first fragment works and other's don't. I'm assuming the differences are due to object destruction and scoping rules. I'm looking for an explanation of why the first fragment works and the other fragments hang on close(). Also, what can the SDK do to eliminate future mistakes. Some really smart people looked at the fragment but never saw the issue.
First code fragment. This fragment works and is shown in its entirety. Subsequent code fragments replace the marked code within. Please focus on the differences and not other distractions. The code was tested by making a single GET request in a browser and stepping through the code. In all cases, request.reply() was executed once and only once.
boost::lockfree::spsc_queue<web::http::http_request, boost::lockfree::capacity<1024>> queue;
web::http::experimental::listener::http_listener listener(U("http://localhost:3901"));
listener.support([&](web::http::http_request request)
{
queue.push(request);
});
listener.open().wait();
std::cout << "listening ... hit enter to initiate shutdown." << std::endl;
std::getchar();
// BEGIN CODE IN QUESTION
while (!queue.empty())
{
web::http::http_request request;
if (queue.pop(request))
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
}
// END CODE IN QUESTION
listener.close().wait();
Second code fragment. Hangs on close().
// hangs on close().wait()
web::http::http_request request;
while (queue.try_pop(request))
{
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
}
Third code fragment. Hangs on close().
// hangs on close().wait(). Outer braces make no difference.
{
web::http::http_request request;
while (queue.try_pop(request))
{
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
request.~http_request();
}
}
Forth code fragment. Hangs on close(). Outer braces make no difference.
// hangs on close().wait()
{
web::http::http_request request;
while (queue.try_pop(request))
{
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
request.~http_request();
}
request.~http_request();
}
Update: Supporting Matt McNabb's explanation, the following code works if I only issue one GET. I simply removed the loop to process the single GET. The explicit destructor call is required to avoid a hang but it's incorrect practice.
web::http::http_request request;
requests.pop(request);
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
request.~http_request();
Update: An explicit destructor call after the loop makes the program work for a single GET. However, two or more GETs throw an exception. I'm unsure why.
web::http::http_request request;
while (queue.try_pop(request))
{
request.reply(web::http::status_codes::ServiceUnavailable, U("Service Unavailable")).wait();
}
request.~http_request();