Как мне повлиять на изменение системных часов во время ожидания на std :: condition_variable?

Я пытаюсь внедрить кросс-платформенный код в C ++ 11. Часть этого кода реализует объект семафора, используя wait_until . Когда мне нужно выполнить время ожидания на семафоре, я использую wait_until или wait_for.

Проблема, которую я испытываю, заключается в том, что стандартная реализация condition_variable в системах на основе POSIX зависит от системных часов, а не от монотонных часов (см. Также: эта проблема против спецификации POSIX )

Это означает, что если системные часы будут изменены до некоторого времени в прошлом, моя переменная состояния будет блокироваться намного дольше, чем я ожидаю. Например, если я хочу, чтобы мое condition_variable таймаутировалось через 1 секунду, если кто-то настраивает часы на 10 минут во время ожидания, condition_variable блокирует 10 минут + 1 секунду. Я подтвердил, что это поведение в системе Ubuntu 14.04 LTS.

Мне нужно полагаться на этот таймаут, чтобы быть хотя бы несколько точным (т. Е. Он может быть неточным в пределах некоторого предела погрешности, но все равно необходимо выполнить, если системные часы меняются). Похоже, что мне нужно будет написать свою собственную версию condition_variable, которая использует функции POSIX и реализует один и тот же интерфейс, используя монотонные часы.

Это звучит как «Много работы» - и вроде беспорядок. Есть ли другой способ обойти эту проблему?

c++,c++11,time,condition-variable,system-clock,

10

Ответов: 3


1

Зарегистрируйте активные переменные состояния централизованно.

Приложите некоторое усилие для обнаружения ошибки часов, даже если это блокировка вращения нити на текущих часах (ick) или некоторых других средствах.

Когда вы обнаруживаете ошибку синхронизации, перепутайте переменную условия.

Теперь оберните переменные условия в тонкую оболочку, которая также поддерживает обнаружение проскальзывания часов. Он вызывает, wait_untilно заменяет предикат тем, который обнаруживает проскальзывание часов, а когда это происходит, вырывается из ожидания.

Когда ваша реализация нарушена, вы должны делать то, что должны делать.


1 принят

Рассмотрев возможные решения этой проблемы, наиболее целесообразным является запрет на использование std :: condition_variable (или, по крайней мере, сделать оговорку понятной, что она всегда будет использовать системные часы). Затем я должен в основном переустановить условие condition_variable стандартной библиотеки, чтобы уважать выбор часов.

Поскольку мне приходится поддерживать несколько платформ (Bionic, POSIX, Windows и, в конечном счете, MacOS), это означает, что я буду поддерживать несколько версий этого кода.

Хотя это противно, кажется, что альтернативы еще более противные.


0

Это может быть не лучшее решение или отличное решение, но вы сказали «работать», а не «много работы», поэтому:

  • Используйте средства вашего дистрибутива для мониторинга изменений в системных часах (я не совсем уверен, что это за объекты, в худшем случае вы можете запускать работу cron каждые 5 минут, чтобы проверить, что часы находятся вокруг ожидаемого значения).
  • После обнаружения изменения системных часов сообщите что-то процессу, в котором у вас есть ваши ожидания / спальные потоки. Вы можете использовать сигнал; или трубы; или сокет unix-domain; или даже с разделяемой памятью.
  • На стороне процесса убедитесь, что вы получили это (т. Е. Записываете обработчик сигнала или имеете поток, делающий блокировку ввода-вывода на трубе, или опроса разделяемой памяти с помощью не- std::condition_variableсна - соответственно)
  • Получив уведомление об изменении системных часов, встряхните вещи в своем процессе, пробудите спящие потоки и переоцените, что нужно делать на основе измененного времени. Возможно, это точно так же, как и раньше, и в этом случае вы снова используете свои потоки, используя переменную условия.

Не очень элегантный, и есть куча накладных расходов, - но это имеет смысл и не является сумасшедшим взломом.

C ++, C ++ 11, время, состояние переменной, системы синхронизации,
Похожие вопросы
Яндекс.Метрика