web-dev-qa-db-ja.com

C ++で関数のタイムアウトを実装する方法

私は関数fを持っています。開始fの後に例外1をスローしたい。 f()は変更できません。 c ++でそれを行うことは可能ですか?

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

別のスレッドを作成して、呼び出し自体を実行し、メインスレッドで条件変数を待機して、戻り時にfへの呼び出しを行うスレッドによって通知されるようにすることができます。トリックは、1秒のタイムアウトで条件変数を待機することです。これにより、呼び出しがタイムアウトよりも長い場合でも、ウェイクアップし、それを認識して、例外をスローできるようになります(すべてメインスレッドで)。これがコードです(ライブデモ 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;
}
12
Smeeheey

std :: packaged_task を使用して、別のスレッドで関数を実行することもできますf()このソリューションは、多かれ少なかれ this に似ています= 1つ、標準のクラスを使用して処理を終了することのみ。

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)
{
   future.get(); // this will propagate exception from f() if any
}
else
{
   thr.detach(); // we leave the thread still running
   throw std::runtime_error("Timeout");
}
3
Alex Che

新しいスレッドを作成し、1が渡されるのを非同期的に待機してから、例外をスローできます。ただし、例外はスローされた同じスレッドでのみキャッチできるため、サンプルコードのように、f()を呼び出した同じスレッドでキャッチすることはできません。ただし、これは要件ではありません。それで大丈夫かもしれません.

fが1秒未満で戻ることが保証されている場合にのみ、これを同期的に行うことができます。

  • 現在の時刻を保存
  • 呼び出しf()
  • 現在の時間を待つ-保存された時間+ 1秒

しかし、実際にfが時間内に戻ることを証明するのは非常に難しい場合があります。

1
eerorika