C++ 如何在C++中实现函数的超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40550730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement timeout for function in c++
提问by Newbie
I have got function f; I want to throw exception 1s after start f. I can't modify f(). It it possible to do it in c++?
我有函数 f; 我想在启动 f 后抛出异常 1s。我无法修改 f()。可以用 C++ 来做吗?
try {
f();
}
catch (TimeoutException& e) {
//timeout
}
回答by Smeeheey
You can create a separate thread to run the call itself, and wait on a condition variable back in your main thread which will be signalled by the thread doing the call to f
once it returns. The trick is to wait on the condition variable with your 1s timeout, so that if the call takes longer than the timeout you will still wake up, know about it, and be able to throw the exception - all in the main thread. Here is the code (live demo here):
您可以创建一个单独的线程来运行调用本身,并在主线程中等待一个条件变量,f
一旦它返回,执行调用的线程就会发出信号。诀窍是在 1s 超时的情况下等待条件变量,这样如果调用时间超过超时时间,您仍然会醒来,知道它,并能够抛出异常 - 全部在主线程中。下面是代码(现场演示这里):
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std::chrono_literals;
int f()
{
std::this_thread::sleep_for(10s); //change value here to less than 1 second to see Success
return 1;
}
int f_wrapper()
{
std::mutex m;
std::condition_variable cv;
int retValue;
std::thread t([&cv, &retValue]()
{
retValue = f();
cv.notify_one();
});
t.detach();
{
std::unique_lock<std::mutex> l(m);
if(cv.wait_for(l, 1s) == std::cv_status::timeout)
throw std::runtime_error("Timeout");
}
return retValue;
}
int main()
{
bool timedout = false;
try {
f_wrapper();
}
catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
timedout = true;
}
if(!timedout)
std::cout << "Success" << std::endl;
return 0;
}
回答by Alex Che
You can also use std::packaged_taskto run your function f() in another thread. This solution is more or less similar to thisone, only that it uses standard classes to wrap things up.
您还可以使用std::packaged_task在另一个线程中运行您的函数 f() 。这个解决方案或多或少类似于这个,只是它使用标准类来包装。
std::packaged_task<void()> task(f);
auto future = task.get_future();
std::thread thr(std::move(task));
if (future.wait_for(1s) != std::future_status::timeout)
{
thr.join();
future.get(); // this will propagate exception from f() if any
}
else
{
thr.detach(); // we leave the thread still running
throw std::runtime_error("Timeout");
}
You can probably even try to wrap it into a function template, to allow calling arbitrary functions with timeout. Something along the lines of:
您甚至可以尝试将其包装到函数模板中,以允许在超时时调用任意函数。类似的东西:
template <typename TF, typename TDuration, class... TArgs>
std::result_of_t<TF&&(TArgs&&...)> run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
{
using R = std::result_of_t<TF&&(TArgs&&...)>;
std::packaged_task<R(TArgs...)> task(f);
auto future = task.get_future();
std::thread thr(std::move(task), std::forward<TArgs>(args)...);
if (future.wait_for(timeout) != std::future_status::timeout)
{
thr.join();
return future.get(); // this will propagate exception from f() if any
}
else
{
thr.detach(); // we leave the thread still running
throw std::runtime_error("Timeout");
}
}
And then use:
然后使用:
void f1() { ... }
call_with_timeout(f1, 5s);
void f2(int) { ... }
call_with_timeout(f2, 5s, 42);
int f3() { ... }
int result = call_with_timeout(f3, 5s);
This is an online example: http://cpp.sh/7jthw
这是一个在线示例:http: //cpp.sh/7jthw
回答by eerorika
You can create a new thread and asynchronously wait for 1s to pass, and then throw an exception. However, exceptions can only be caught in the same thread where they're thrown, so, you cannot catch in the same thread where you called f()
, like in your example code - but that's not a stated requirement, so it may be OK for you.
可以新建一个线程,异步等待1s过去,然后抛出异常。但是,异常只能在抛出它们的同一个线程中捕获,因此,您不能在调用的同一个线程中捕获异常,f()
就像在示例代码中一样 - 但这不是规定的要求,因此对您来说可能没问题.
Only if f
is guaranteed to return in less than 1s, can you do this synchronously:
只有f
保证在1s以内返回,才可以同步执行:
- store current time
- call
f()
- wait for current time - stored time + 1s
- 存储当前时间
- 称呼
f()
- 等待当前时间 - 存储时间 + 1s
But it may be quite difficult to prove that f
in fact does return in time.
但要证明f
事实上确实及时返回可能相当困难。