I have the following code to run a timed thread:
// Method to invoke a request with a timeout.
bool devices::server::CDeviceServer::invokeWithTimeout(CDeviceClientRequest& request,
CDeviceServerResponse& response)
{
// Retrieve the timeout from the device.
int timeout = getTimeout();
timeout += 500; // Add 500ms to cover invocation time.
// Invoke the request within a timed thread.
boost::promise<void> boostPromise;
boost::unique_future<void> boostFuture = boostPromise.get_future();
boost::thread boostThread([&]()
{
invoke(request, response);
boostPromise.set_value();
});
// The thread has timed out, if the future is not ready.
return (boostFuture.wait_for(boost::chrono::milliseconds(timeout))
==
boost::future_status::ready);
}
This appears to work without a problem, the function returns false when it times out.
However, then the code being invoked (by invoke(request, response);) throws an exception which kills the application. How do I successfully terminate the thread if it has not completed, and consume any exceptions.
I have tried the following:
// The thread has timed out, if the future is not ready.
bool completed = (boostFuture.wait_for(boost::chrono::milliseconds(timeout))
==
boost::future_status::ready);
if (!completed)
{
boostThread.interrupt();
}
return completed;
But this also throws an exception and crashes the application. I need a completely safe mechanism where the timed thread can be safely killed off, if the timeout has been reached.
Boost documentation states:
If the function or callable object passed to the boost::thread constructor propagates an exception when invoked that is not of type boost::thread_interrupted, std::terminate() is called.
You must catch the exception and exit the thread cleanly (or throw boost::thread_interrupted)
OK, the code I came up with as a solution is:
// Functor to help invoke the device method, inside a timed thread.
struct invoke_fn
{
void operator()(devices::server::CDeviceServer& server,
boost::promise<void>& boostPromise,
CDeviceClientRequest& request,
CDeviceServerResponse& response)
{
try
{
server.invoke(request, response);
boostPromise.set_value();
}
catch (devices::util::CDeviceException &e)
{
// Add any error to the response.
std::string message = devices::util::retrieveDeviceExceptionMessage(e);
response.set_errormessage(message);
}
catch (std::exception &e)
{
// Add any exception message to the response.
std::string message(e.what());
response.set_errormessage(message);
}
}
};
// Method to invoke a request with a timeout.
bool devices::server::CDeviceServer::invokeWithTimeout(CDeviceClientRequest& request,
CDeviceServerResponse& response)
{
// Retrieve the timeout from the device.
int timeout = getTimeout();
timeout += 500; // Add 500ms to cover invocation time.
// Invoke the request within a timed thread.
boost::promise<void> boostPromise;
boost::unique_future<void> boostFuture = boostPromise.get_future();
boost::thread boostThread([&]()
{
invoke_fn functor;
functor(*this,
boostPromise,
request,
response);
});
// The thread has timed out, if the future is not ready.
return (boostFuture.wait_for(boost::chrono::milliseconds(timeout))
==
boost::future_status::ready);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.