How to implement timeout for function in c++

2019-02-15 19:27发布

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++?

try {
   f();
}
catch (TimeoutException& e) {
//timeout
}

2条回答
趁早两清
2楼-- · 2019-02-15 19:37

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.

Only if f is guaranteed to return in less than 1s, can you do this synchronously:

  • store current time
  • call f()
  • wait for current time - stored time + 1s

But it may be quite difficult to prove that f in fact does return in time.

查看更多
Luminary・发光体
3楼-- · 2019-02-15 19:38

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):

#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;
}
查看更多
登录 后发表回答