gpt4 book ai didi

c++ - Boost.Thread 在 1.58 中醒来得太晚

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:30:47 24 4
gpt4 key购买 nike

我有一个应用程序需要在某些窗口内工作(在本例中,窗口都相隔 30 秒)。当时间不在一个窗口内时,计算到下一个窗口中间的时间,线程休眠这段时间(以毫秒为单位,使用 boost::this_thread::sleep_for) .

使用 Boost 1.55,我能够以极高的可靠性在我的容忍范围内(+/-100 毫秒)击中窗口。迁移到 Boost 1.58 后,我永远无法打开这些窗口。将 boost::this_thread::sleep_for 替换为 std::this_thread::sleep_for 解决了这个问题;但是,我需要 boost::thread 的可中断特性和 boost::this_thread::sleep_for 提供的中断点。

下面是一些说明该问题的示例代码:

#include <boost/thread.hpp>
#include <boost/chrono.hpp>

#include <chrono>
#include <iostream>
#include <thread>

void boostThreadFunction ()
{
std::cout << "Starting Boost thread" << std::endl;
for (int i = 0; i < 10; ++i)
{
auto sleep_time = boost::chrono::milliseconds {29000 + 100 * i};
auto mark = std::chrono::steady_clock::now ();
boost::this_thread::sleep_for (sleep_time);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now () - mark);
std::cout << "Boost thread:" << std::endl;
std::cout << "\tSupposed to sleep for:\t" << sleep_time.count ()
<< " ms" << std::endl;
std::cout << "\tActually slept for:\t" << duration.count ()
<< " ms" << std::endl << std::endl;
}
}

void stdThreadFunction ()
{
std::cout << "Starting Std thread" << std::endl;
for (int i = 0; i < 10; ++i)
{
auto sleep_time = std::chrono::milliseconds {29000 + 100 * i};
auto mark = std::chrono::steady_clock::now ();
std::this_thread::sleep_for (sleep_time);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now () - mark);
std::cout << "Std thread:" << std::endl;
std::cout << "\tSupposed to sleep for:\t" << sleep_time.count ()
<< " ms" << std::endl;
std::cout << "\tActually slept for:\t" << duration.count ()
<< " ms" << std::endl << std::endl;
}
}

int main ()
{
boost::thread boost_thread (&boostThreadFunction);
std::this_thread::sleep_for (std::chrono::seconds (10));
std::thread std_thread (&stdThreadFunction);
boost_thread.join ();
std_thread.join ();
return 0;
}

这是将 Boost 1.58 作为包含目录引用并在我的工作站(Windows 7 64 位)上运行时的输出:

Starting Boost thread
Starting Std thread
Boost thread:
Supposed to sleep for: 29000 ms
Actually slept for: 29690 ms

Std thread:
Supposed to sleep for: 29000 ms
Actually slept for: 29009 ms

Boost thread:
Supposed to sleep for: 29100 ms
Actually slept for: 29999 ms

Std thread:
Supposed to sleep for: 29100 ms
Actually slept for: 29111 ms

Boost thread:
Supposed to sleep for: 29200 ms
Actually slept for: 29990 ms

Std thread:
Supposed to sleep for: 29200 ms
Actually slept for: 29172 ms

Boost thread:
Supposed to sleep for: 29300 ms
Actually slept for: 30005 ms

Std thread:
Supposed to sleep for: 29300 ms
Actually slept for: 29339 ms

Boost thread:
Supposed to sleep for: 29400 ms
Actually slept for: 30003 ms

Std thread:
Supposed to sleep for: 29400 ms
Actually slept for: 29405 ms

Boost thread:
Supposed to sleep for: 29500 ms
Actually slept for: 29999 ms

Std thread:
Supposed to sleep for: 29500 ms
Actually slept for: 29472 ms

Boost thread:
Supposed to sleep for: 29600 ms
Actually slept for: 29999 ms

Std thread:
Supposed to sleep for: 29600 ms
Actually slept for: 29645 ms

Boost thread:
Supposed to sleep for: 29700 ms
Actually slept for: 29998 ms

Std thread:
Supposed to sleep for: 29700 ms
Actually slept for: 29706 ms

Boost thread:
Supposed to sleep for: 29800 ms
Actually slept for: 29998 ms

Std thread:
Supposed to sleep for: 29800 ms
Actually slept for: 29807 ms

Boost thread:
Supposed to sleep for: 29900 ms
Actually slept for: 30014 ms

Std thread:
Supposed to sleep for: 29900 ms
Actually slept for: 29915 ms

我希望 std::threadboost::thread 休眠相同的时间;然而,boost::thread 在被要求休眠 29.1 - 29.9 秒时似乎想要休眠 ~30 秒。我是否滥用了 boost::thread 接口(interface),或者这是自 1.55 以来引入的错误?

最佳答案

我是将上述更改提交给 Boost.Thread 的人。 1.58 中的这一变化是在与 Boost 社区和 Microsoft 协商一段时间后设计的,并且可能会显着改善移动设备的电池生命周期。 C++ 标准不保证任何定时等待实际等待,或等待正确的时间段,或任何接近正确时间段的东西。因此,任何假设定时等待有效或准确的代码都是错误的。 future 的 Microsoft STL 可能会对 Boost.Thread 进行类似的更改,因此 STL 行为将与 Boost.Thread 相同。我可能会补充说,在任何非实时操作系统上,任何定时等待本质上都是不可预测的,可能会比请求的时间晚得多。因此,社区认为此更改有助于揭露 STL 的错误使用。

此更改允许 Windows 有选择地延迟一定时间触发计时器。它实际上可能不会这样做,实际上只是试图延迟常规中断,作为最新版本 Windows 上无滴答内核设计的一部分。即使您指定了数周的容差,因为正确的截止日期总是发送到 Windows,在计时器到期后发生的下一个系统中断将始终触发计时器,因此没有计时器最多会延迟几秒钟。

此更改修复的一个错误是系统 sleep 问题。以前的实现可能会因系统休眠而感到困惑,因为定时等待永远不会醒来(好吧,29 天后他们会)。这个实现正确地处理了系统休眠,希望由系统休眠导致的使用 Boost.Thread 的代码随机挂起现在已成为过去。

最后,我个人认为定时等待在STL中需要一个硬/软保证。然而,这是一个相当大的变化。即使实现了,除了在硬实时操作系统上,定时等待的困难也只能是尽力而为。这就是为什么它们首先被排除在 C++ 标准之外,因为 C++ 11 在移动设备功耗被认为重要到足以修改 API 之前就已经完成。

尼尔

关于c++ - Boost.Thread 在 1.58 中醒来得太晚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30381866/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com