【问题标题】:C++11 execute block in same thread but with timeoutC ++ 11在同一线程中执行块但超时
【发布时间】:2017-03-13 18:54:02
【问题描述】:

假设我们有一段代码,我们只是不能修改它,但我们想破坏它,当它运行时间过长(x 毫秒)时退出这段代码

伪代码

Throw exception after (500ms) {
    auto result = Do some risky job, for example test string by regex with catastrophic backtracking risk.
}
catch ( Exception e ) {
    //... 
}

每件事都必须在同一个线程中。

是否可以使用 c++11 或其他标准?

【问题讨论】:

  • 操作系统重要吗 - 例如,Linux 上的 SIG_ALARM 肯定会允许这样做#
  • @UKMonkey:这是针对 FreeBSD 下的 node.js 插件的。但我想每个信息都会有所帮助。
  • 最简单的方法是在单独的线程上实际运行有风险的业务。然后,您使用en.cppreference.com/w/cpp/thread/future/wait_forstd::future 中等待结果。
  • @StoryTeller 这是最后一种方式。我希望它不是异步的
  • 它怎么比一个神奇地让你抛出异常的随机信号更异步?

标签: c++ regex c++11 thread-safety boost-regex


【解决方案1】:

FreeBSD(以及所有其他 linux 类型)具有“SigAlarm”:Reference here

这将允许您设置计时器;当事件被触发时,您当前的代码被中断,并调用信号处理程序,由您之前对signal的调用设置@

这将允许您设置一个标志,您的非常危险的线程可以检查该标志;如果需要,然后抛出。

它不允许您以您想要的方式直接引发异常,但它允许您保持应用程序单线程。

【讨论】:

  • 实际上,当使用 setjmp/longjmp 和信号处理程序时,你甚至可以抛出。我曾经用它来将信号转换为 C++ 异常。
  • 跳远示例here
  • setjmp/longjmp 而自动存储中有 RAII 对象不是一个好主意。
  • @Yakk 老实说,不使用另一个线程来实现这个概念并不是一个好主意,但中断是以单线程方式执行此操作的唯一方法。
  • @ukmonkey 是的,但旗帜至少不会破坏世界。 setjmp/longjmp 确实,不用担心你正在使用它们来拥有堆栈协程或类似的东西,这里不是这种情况。
【解决方案2】:

一般来说,如果没有在代码中或在代码调用的代码中引发异常的代码,C++ 无法在代码中引发异常。

您可以嵌入 ASL、脚本语言或单独的进程。所有 3 个都可以设计为被中断(例如,可以终止进程)。

Boost 具有可中断的线程。它的工作原理是它在 boost 同步原语(互斥锁等)中有钩子,因此当您与它们交互时,它会检查您的线程是否已被告知停止。如果是,则抛出异常。

一个简单的部分解决方案是

std::vector<std::future<R()>> futures;
futures.push_back( std::async( std::launch::async, []()->R{ /* code */ ) );
using std::chrono::literals;
if (futures.back().wait_for(500ms)==std::future_status::ready) {
  auto r = futures.back().get();
  futures.pop_back();
  clear_ready_futures(futures); // wait for 0ms and if so, discard and destroy
  return r;
}
// failed case

这里我们的futures 存储了已失效的期货(实际上是线程)。 clear_ready_futures 清除所有已完成的旧文件。

已经开始的任务仍然会运行到完成,占用cpu,但调用代码不必等待它们。

【讨论】:

  • 如果经常发生,我是否应该考虑保留一个线程,然后将工作发送给他?而不是每次我有工作要做时都创建一个新的?
  • 还有一个问题。它会显着减慢代码速度吗?通常不会超时的代码。
  • 当然,作业队列和线程池很容易编写(很多都可以在 SO 上找到)。显着取决于什么是显着的:ns、ms、s?真的,测量。
  • 它似乎仍在等待代码执行,即使超时为 2000 毫秒:pastebin.com/Jm8v8d9y
  • 是否有办法在超时后停止运行作业?
猜你喜欢
  • 2019-02-27
  • 1970-01-01
  • 2015-07-04
  • 2017-01-09
  • 2013-07-31
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多