私は関数fを持っています。開始fの後に例外1をスローしたい。 f()は変更できません。 c ++でそれを行うことは可能ですか?
try {
f();
}
catch (TimeoutException& e) {
//timeout
}
別のスレッドを作成して、呼び出し自体を実行し、メインスレッドで条件変数を待機して、戻り時に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;
}
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");
}
新しいスレッドを作成し、1が渡されるのを非同期的に待機してから、例外をスローできます。ただし、例外はスローされた同じスレッドでのみキャッチできるため、サンプルコードのように、f()
を呼び出した同じスレッドでキャッチすることはできません。ただし、これは要件ではありません。それで大丈夫かもしれません.
f
が1秒未満で戻ることが保証されている場合にのみ、これを同期的に行うことができます。
f()
しかし、実際にf
が時間内に戻ることを証明するのは非常に難しい場合があります。