Sco*_*t M 6 c++ boost boost-thread
我有一个应用程序,需要在某些窗口内工作(在这种情况下,窗口相隔30秒).当时间不在窗口内时,计算下一个窗口中间的时间,并且线程休眠该时间量(以毫秒为单位,使用boost::this_thread::sleep_for).
使用Boost 1.55,我能够在极限可靠性的范围内(+/- 100ms)击中窗户.在迁移到Boost 1.58后,我无法打到这些窗口.替换boost::this_thread::sleep_forwith 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;
}
Run Code Online (Sandbox Code Playgroud)
以下是将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
Run Code Online (Sandbox Code Playgroud)
我希望std::thread和boost::thread睡觉的时间相同; 然而,boost::thread当被要求睡了29.1 - 29.9秒时,似乎想要睡30秒.我是否滥用boost::thread界面,或者这是自1.55以来引入的错误?
我是将上述更改提交给Boost.Thread的人.1.58的这一变化是在与Boost社区和微软进行了一段时间的协商之后设计的,并且导致移动设备上的电池寿命大大改善.C++标准不保证任何定时等待实际等待,或等待正确的时间段,或任何接近正确的时间段.因此,为了假定定时等待工作或准确而编写的任何代码都是错误的.未来的Microsoft STL可能会对Boost.Thread进行类似的更改,因此STL行为与Boost.Thread相同.我可能会在任何非实时操作系统上添加它,任何定时等待本质上都是不可预测的,任何时候都可能比请求时间大得多.因此,社区认为这种变化有助于暴露STL的错误使用.
此更改允许Windows可选地延迟一定量的计时器.它可能实际上并没有这样做,实际上只是试图延迟常规中断,作为最新版Windows上无滴答内核设计的一部分.即使您指定了几周的容差,因为正确的截止日期始终发送到Windows,在计时器到期后发生的下一个系统中断将始终触发计时器,因此没有计时器最多会延迟超过几秒钟.
这种变化导致的一个错误就是系统睡眠问题.以前的实现可能会被系统睡眠混淆,因为定时等待永远不会被唤醒(好吧,他们会在29天内).这个实现正确地处理了系统休眠,并且使用由系统休眠引起的Boost.Thread的代码随机挂起现在已成为过去.
最后,我个人认为定时等待需要STL中的硬度/柔软度保证.然而,这是一个非常大的变化.即使实施,除了在硬实时操作系统上,定时等待的硬度只能是最好的努力.这就是为什么他们首先被排除在C++标准之外,因为在移动设备功耗被认为足以修改API之前,C++ 11已经完成.
尼尔