簡體   English   中英

C++ 為類方法實現超時函數模板

[英]C++ Implementing a timeout function template for class methods

我想要實現的目標是讓程序停止進程並在進程超過超時時間時返回超時錯誤。

我從這個問題第二個投票最多的答案中得到了一個超時函數。 我遇到了一個錯誤,它說std::result_of_t在 c++17 中已被棄用,所以我使用建議的替換std::invoke_result_t重新創建了它,並像這樣實現它:

template <typename TF, typename TDuration, class... TArgs>
std::invote_result_t<TF&&, TArgs&&...> run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
{
    using R = std::invoke_result_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");
    }
}

我想用它來檢查類方法函數的超時。 所以我嘗試以類似於以下方式使用它:

template <typename TF, typename TDuration, class... TArgs>
std::invote_result_t<TF&&, TArgs&&...> ClassOne::run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
{
    using R = std::invoke_result_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");
    }
}

// The function checked for timeout
int ClassOne::func(ClassTwo *param1, std::string name)
{
    // Some code here...

    // For mimicking function process:
    std::this_thread::sleep_for(10s);
    return 0;
}

// Function which calls the timed process with timeout function
int ClassOne::dummy(ClassTwo *param1, std::string name)
{
    int retVal = 0; // zero for no error, non-zero for error
    try
    {
        retVal = run_with_timeout(func, 20s, param1, name);
    }
    catch (runtime_error & e)
    {
        return 1;
    }
}

有了這個,我得到了錯誤:

no instance of function template "ClassOne::run_with_timeout" matches the argument list
    argument types are: (int (ClassTwo *param1, std::string target), std::chrono::seconds, ClassTwo *, std::string)

我認為問題與此條目類似,但我不知道如何更正。 我需要使用超時函數的一些函數具有不同的對象參數,這就是使用函數模板的原因。

非常感謝您的幫助!

顧名思義, std::invoke_result_t是應用std::invoke的結果類型。 我在這里強調了適用於您的案例:

INVOKE(f, t1, t2, ..., tN) 定義如下:
...
如果 f 是指向 T 類成員函數的指針:

  • 若 std::is_base_of<T, std::decay_t<decltype(t1)>>::value 為真,則 INVOKE(f, t1, t2, ..., tN) 等價於 (t1.*f)( t2, ..., tN)
  • 如果 t1 不滿足前面的項,則 INVOKE(f, t1, t2, ..., tN) 等價於 ((*t1).*f)(t2, ..., tN)。

所以你的電話應該是:

retVal = run_with_timeout(&ClassOne::func, 20s, this, std::move(param1), std::move(name));

編輯:我掙扎了二十分鍾才讓它真正工作。 如上所述添加std::move或通過 const 引用(在dummy )取name使其編譯。 我想不出param1的類似轉換。 我很想知道該錯誤背后的原因,但至少您的直接問題已解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM