2016-11-11 39 views
1

我有函數f; 我想在開始f後拋出異常1。 我無法修改f()。它有可能在C++中做到這一點?如何實現超時功能,在C++中

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

的可能的複製[什麼是創建一個while循環超時最徹底的方法?(http://stackoverflow.com/questions/2135981/what-是最乾淨的方式來創建一個while循環超時) –

+0

你可以修改代碼*調用*'f'?即'try'塊內的代碼? –

+0

是的,我可以修改代碼調用f – Newbie

回答

4

您可以創建一個單獨的線程來運行調用本身,並在主線程中等待條件變量,一旦線程返回,將通過線程發信號給f。訣竅是等待條件變量和你的1s超時,這樣如果調用比超時還要長,你仍然會醒來,知道它,並且能夠拋出異常 - 全部在主線程中。下面是代碼(現場演示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([&m, &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; 
} 
+1

不停止'f()'運行。如果在第一次嘗試退出f()''之前再次運行'f()'線程安全?看起來這可能會造成更多問題。 –

+0

OP沒有聲明停止'f'是一個要求。重新進入/線程安全問題可以通過進一步闡述用這種方法解決 - 這裏的內容足以證明本質。 – Smeeheey

1

您可以創建一個新的線程並異步等待1s傳遞,然後拋出一個異常。然而,例外只能在他們扔在同一個線程抓住了,所以,你不能在你叫f(),就像在你的示例代碼相同的搭線 - 但是這不是一個規定的要求,所以它可能是OK您。

只有f保證在不到1秒回,你可以這樣做同步:

  • 店當前時間
  • 呼叫f()
  • 等待當前時間 - 存儲時間+ 1秒

但是要證明f事實上確實會及時返回可能相當困難。