std :: chrono :: duration :: max () не работает с библиотекой поддержки потоков - PullRequest
0 голосов
/ 01 декабря 2018

Я хочу создать оболочку вокруг std::timed_mutex с концепцией INFINITY, NOTIMEOUT и значимым тайм-аутом вместо использования различных библиотечных вызовов (lock, try_lock и т. Д.).

Я предположил, что если я использую максимальное разрешение, std::chrono::nanoseconds, его max() продолжительность будет соответствовать 292 годам.Этого более чем достаточно, чтобы представить концепцию INFINITY.

Однако я обнаружил, что это не сработает, если я буду использовать STL chrono типы вспомогательных библиотек, т.е. std::timed_mutex.try_lock_for(std::chrono::nanoseconds::max()) завершает работу (false) сразу же, когдазамок принадлежит другому потоку.Сделайте короткое демонстрационное приложение.

#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;
}

Для этого теста я использовал библиотеку pthread в Ubuntu.

Мои вопросы:

  • Является ли это "ограничением" библиотеки pthread?Ведь длительность max() соответствует максимальному значению rep.

  • Определены ли эти максимальные значения где-нибудь?

  • Это максимальное значениезначения, связанные с тактовой частотой процессора?И может варьироваться в зависимости от архитектуры?

  • Я что-то делаю глупо?

1 Ответ

0 голосов
/ 01 декабря 2018

std::timed_mutex::try_lock_for вычисляет новое значение std::chrono::time_point, при котором должен срабатывать тайм-аут, на основе текущего момента времени и добавления запрошенной длительности тайм-аута.

Для любых ненулевой момент времени, представляющий текущее время (либо время с начала эпохи, либо время с момента последней перезагрузки), разрешение которого составляет не менее несекунд (например, микросекунд), такая операция переполняется при добавлении nanoseconds::max() (с учетом разрешения часов), т.е.:

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

переполняется так же, как:

int{1} + std::numeric_limits<int>::max()

переполняется, потому что std::chrono::nanoseconds::max() возвращает [time.traits.duration_values] / p6 :

static constexpr Rep max() noexcept;

Возвращает : numeric_­limits<Rep>::max().

Разрешение ваших часов, вероятно, установлено на nanoseconds.

...