C++实现类方法的超时函数模板



我想要实现的目标是让程序停止进程,并在进程超过超时时间时返回超时错误。

我从这个问题的第二多投票的答案中得到了一个超时函数。我遇到一个错误,说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<下降型(t1(>gt;:值为true,则INVOKE(f,t1,t2,…,tN(等于(t1.*f((t2
  • 如果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或通过常量引用取name(在dummy中(使其编译。我想不出param1有类似的转换。我很想知道这个错误背后的原因,但至少你眼前的问题已经解决了。

最新更新