【问题标题】:Multiple timeouts in C++C++ 中的多次超时
【发布时间】:2015-01-22 08:40:39
【问题描述】:

我需要使用生存时间参数维护几个对象,并在它们超时时触发某种事件。

将此实现为一个计时器,它只等待具有最小 TTL 的对象,然后再将其从队列中弹出,这似乎不是很有效,因为我需要能够偶尔从该队列中添加/删除对象(他们可以有任何超时值),可能在超时之前。例如,如果我认为最短的 TTL 对象是 10 秒并阻塞超时线程 10 秒,但在此期间将一个具有 3 秒生存时间的对象添加到队列中,则会发生丑陋的事情。

天真的做法

while (true) {
 update()
}

void update() {
 // get delta since last call to update()
 // subtract delta from each object and time out if ttl < 0
}

非常慢,因为有大量内存被洗牌,其唯一目的是在微秒分辨率上更新 ttl。

有没有不为每个对象创建单独线程的好方法?

我可以访问 C++11 标准库,但没有 boost 或任何外部库。

【问题讨论】:

    标签: c++ multithreading timeout


    【解决方案1】:

    一个简单但有点蹩脚的选项是轮询队列的更新 - 比如每秒或十分之一秒。太频繁了,您的操作系统可能没有时间为一些富有成效的工作让步;太不频繁了,你的计时能力变得非常粗糙。您可以使用std::this_thread::sleep_for(std::chrono::milliseconds(n)) 进行轮询延迟,或者可能想要使用例如select 如果你也在做其他 I/O。您可以对由互斥体仲裁的队列进行任何访问,并使用 std::map&lt;std::chrono::time_point, Task&gt; 来保持 Tasks 按 TTL 排序,因此每次轮询期到期时,您只需从 .begin() 迭代到 .end(),提前退出如果time_point 还没有过去。

    ...不为每个对象创建单独的线程?

    如果需要,以上可以通过单个后台线程来完成。

    另一种选择:非标准操作系统提供的异步通知机制,例如发出信号的警报...例如alarm,但是您的信号通常只允许执行相当有限数量的操作,通常的建议是设置一个标志,以便被中断的线程可以知道它有工作要做 - 这与必须检查没有太大区别无论如何,过期的Tasks 的队列,但优点是信号本身可以强制一些阻塞操作提前终止(例如,没有SA_RESTART 标志到sigaction),错误代码指示中断的原因。几十年前,我在一些操作系统上遇到了一些阻塞操作,这些操作对被中断的例程可能一直在使用的 I/O 缓冲区的状态提供了有限的保证,因此无法构建该 I/O 的稳健恢复 - 检查您的操作系统文档.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2019-09-06
      • 1970-01-01
      相关资源
      最近更新 更多