提升timed_wait闰秒问题

时间:2010-05-06 21:26:23

标签: c++ boost

我正在使用来自boost C ++库的timed_wait,我遇到了闰秒的问题。

这是一个快速测试:

#include <boost/thread.hpp>
#include <stdio.h>
#include <boost/date_time/posix_time/posix_time.hpp>

int main(){
        // Determine the absolute time for this timer.
        boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(35000);

        bool done;
        boost::mutex m;
        boost::condition_variable cond;

        boost::unique_lock<boost::mutex> lk(m);
        while(!done)
        {
            if(!cond.timed_wait(lk,tAbsoluteTime))
            {
                done = true;
                std::cout << "timed out";
            }
        }
        return 1;
}

timed_wait函数比它应该提前24秒返回。 24秒是UTC的当前闰秒数。

因此,boost被广泛使用,但我找不到有关此特定问题的任何信息。还有其他人遇到过这个问题吗?可能的原因和解决方案是什么?

注意:我在linux系统上使用boost 1.38。我听说这个问题在MacOS上没有发生。

更新:更多信息:这是在2台内核2.6.9的redhat机器上发生的。我在内核2.6.30的ubuntu机器上执行了相同的代码,并且计时器的行为符合预期。

所以,我认为这可能是由操作系统或redhat机器上的一些错误设置引起的。

我编写了一个解决方法,用于调整UTC的时间,而不是从此调整中获得差异并添加到原始时间。这对我来说是一个坏主意,因为如果这个代码在没有这个问题的机器上执行,它可能是24s AHEAD。仍然找不到原因。

3 个答案:

答案 0 :(得分:2)

在Linux系统上,系统时钟将遵循POSIX标准,该标准强制要求 没有观察到闰秒!如果您不这么认为,这可能是您所看到的差异的根源。 This document对UTC与其他时间尺度的关系以及如果依赖于操作系统的计时概念可能遇到的问题有一个很好的解释。

答案 1 :(得分:1)

是否有可能提前设置完成并且虚假唤醒导致循环比您预期的更快退出?

答案 2 :(得分:0)

好的,这就是我的所作所为。这是一种解决方法,我对此并不满意,但这是我能想到的最好的方法:

int main(){
        typedef boost::date_time::c_local_adjustor<boost::system_time> local_adj;

        // Determine the absolute time for this timer.
        boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(25000);

        /*
         * A leap second is a positive or negative one-second adjustment to the Coordinated
         * Universal Time (UTC) time scale that keeps it close to mean solar time.
         * UTC, which is used as the basis for official time-of-day radio broadcasts for civil time,
         * is maintained using extremely precise atomic clocks. To keep the UTC time scale close to
         * mean solar time, UTC is occasionally corrected by an adjustment, or "leap",
         * of one second.
         */
        boost::system_time tAbsoluteTimeUtc = local_adj::utc_to_local(tAbsoluteTime);

        // Calculate the local-to-utc difference.
        boost::posix_time::time_duration tLocalUtcDiff = tAbsoluteTime - tAbsoluteTimeUtc;

        // Get only the seconds from the difference. These are the leap seconds.
        tAbsoluteTime += boost::posix_time::seconds(tLocalUtcDiff.seconds());

        bool done;
        boost::mutex m;
        boost::condition_variable cond;

        boost::unique_lock<boost::mutex> lk(m);
        while(!done)
        {
            if(!cond.timed_wait(lk,tAbsoluteTime))
            {
                done = true;
                std::cout << "timed out";
            }
        }
        return 1;
}

我已经在有问题和无问题的机器上进行了测试,并且它在两者上都按预期工作,所以只要我找不到更好的解决方案,我就会保留它。

谢谢大家的帮助。