std :: chrono :: duration :: max()与线程支持库不兼容

时间:2018-12-01 07:12:46

标签: c++ multithreading pthreads c++17 chrono

我希望围绕std::timed_mutex创建一个具有INFINITY,NOTIMEOUT和值超时的概念的包装器,而不是使用不同的库调用(locktry_lock等)。

我假设如果使用最大分辨率std::chrono::nanoseconds,则其max()持续时间将对应292年。足以代表INFINITY的概念。

但是,我发现如果使用STL chrono库帮助程序类型是行不通的,即std::timed_mutex.try_lock_for(std::chrono::nanoseconds::max())在锁被其他线程拥有时立即退出(false)。 Bellow是一个快速演示应用程序。

#include <cstdlib>
#include <ratio>
#include <chrono>
#include <mutex>
#include <thread>
#include <iostream>

#define STR_ME(expr_)   #expr_

template <typename Duration>
void check_infinity(const char *name,const Duration &timeout)
{
    std::timed_mutex tmd_mx;

    tmd_mx.lock();  //mutex is locked by std::this_thread
    auto thread_f=[&](const char *name,Duration timeout)
                {   
                    if (!tmd_mx.try_lock_for(timeout))  
                        std::cout << name << " : TIMEOUT!!" << std::endl;
                    else
                        std::cout << "Green light..." << std::endl;
                };

    std::thread t{thread_f,name,timeout};
    std::this_thread::sleep_for(std::chrono::seconds(2));   //Ensures thread "t" runs.    
    t.join();
    std::cout << "Houston??" << std::endl;  //Shouldn't reach this point ever.
}

int main(int argc, char** argv) 
{
    check_infinity(STR_ME(std::chrono::nanoseconds::max()),std::chrono::nanoseconds::max());    //Fails
    //Every other STL chrono::durations fail.    

    using my_nanoseconds    = std::chrono::duration<unsigned int,std::nano>;   //STL uses long.
    using my_seconds        = std::chrono::duration<unsigned int>;  
    check_infinity(STR_ME(my_nanoseconds::max()),my_nanoseconds::max());  // Fails
    check_infinity(STR_ME(my_seconds::max()),my_seconds::max());  // Works !!

    return EXIT_FAILURE;
}

对于该测试,我在ubuntu中使用了pthread库。

我的问题是:

  • 这是pthread库的“限制”吗?毕竟max()的持续时间对应于rep的最大值。

  • 此最大值在某处定义吗?

  • 此最大值与CPU时钟有关吗?并可能因架构而异?

  • 我在做愚蠢的事吗?

1 个答案:

答案 0 :(得分:2)

std::timed_mutex::try_lock_for根据当前时间点并添加请求的超时时间,计算出一个新的std::chrono::time_point,在该时间应触发超时。

对于表示当前时间(从纪元开始的时间或自上次重新启动以来的时间)的任何非零时间点,其分辨率均不少于毫秒(例如,微秒),当添加{{1}时,此类操作会溢出}(已调整为时钟的分辨率),即:

nanoseconds::max()

溢出就像:

steady_clock::now() + duration_cast<steady_clock::duration>(nanoseconds::max())

溢出,因为int{1} + std::numeric_limits<int>::max() 返回[time.traits.duration_values]/p6

std::chrono::nanoseconds::max()
     

返回static constexpr Rep max() noexcept;

您的时钟分辨率可能设置为numeric_­limits<Rep>::max()