Каков наилучший способ выхода из цикла по истечении 30 мс в С++?

StackOverflow https://stackoverflow.com/questions/946167

  •  09-09-2019
  •  | 
  •  

Вопрос

Каков наилучший способ выхода из цикла как можно ближе к 30 мс в C++.Повышение опроса:microsec_lock ?Опрос QTime?Что-то другое?

Что-то вроде:

A = now;
for (blah; blah; blah) {
    Blah();
    if (now - A > 30000)
         break;
}

Он должен работать в Linux, OS X и Windows.

Вычисления в цикле предназначены для обновления моделирования.Каждые 30 мс я хотел бы обновлять область просмотра.

Это было полезно?

Решение

Пример фрагмента кода по этой ссылке в значительной степени делает то, что вы хотите:

http://www.cplusplus.com/reference/clibrary/ctime/lock/

Адаптировано из их примера:

void runwait ( int seconds )
{
   clock_t endwait;
   endwait = clock () + seconds * CLOCKS_PER_SEC ;
   while (clock() < endwait)
   {
      /* Do stuff while waiting */
   }
}

Другие советы

Расчеты в цикле предназначены для обновления симуляции.Каждые 30 мс я хотел бы обновить просмотр.

Вы рассматривали возможность использования потоков?То, что вы описываете, кажется прекрасным примером того, почему вам следует использовать потоки вместо таймеров.

Основной поток процесса продолжает заботиться о пользовательском интерфейсе, и для его обновления QTimer установлен на 30 мс.Он блокирует КМьютекс чтобы получить доступ к данным, выполняет обновление и освобождает мьютекс.

Вторая тема (см. QThread) выполняет симуляцию.Для каждого цикла он блокирует QMutex, выполняет вычисления и освобождает мьютекс, когда данные находятся в стабильном состоянии (подходящем для обновления пользовательского интерфейса).

С ростом популярности многоядерных процессоров вам следует все больше и больше думать об использовании потоков, а не об использовании таймеров.Ваши приложения автоматически выигрывают от повышенной мощности (многоядерности) новых процессоров.

Хотя это не дает ответа на вопрос, это может дать возможность по-новому взглянуть на решение.А как насчет размещения кода моделирования и пользовательского интерфейса в разных потоках?Если вы используете Qt, периодическое обновление можно реализовать с помощью таймера или даже QThread::msleep().Вы можете адаптировать пример резьбового Мандельброта в соответствии с вашими потребностями.

Если нужно выполнить работу до истечения определенного времени, то ответ docflabby является точным.Однако если вам нужно просто подождать, ничего не делая, пока не истечет указанное время, то следует использовать usleep()

Короткий ответ:в целом вы не можете, но можете, если используете правильную ОС или правильное оборудование.

Вы можете получить БЛИЗКО до 30 мс на всех ОС, используя вызов сборки в системах Intel и что-то еще в других архитектурах.Я найду ссылку и отредактирую ответ, включив в него код, когда найду его.

Проблема заключается в алгоритме квантования времени и в том, насколько близко вы находитесь к концу временного интервала в многозадачной ОС.

В некоторых ОС реального времени в системной библиотеке есть системный вызов, но я не уверен, что это будет за вызов.

редактировать:РЖУ НЕ МОГУ!Кто-то уже опубликовал подобный фрагмент на SO: Функция таймера для предоставления времени в наносекундах с использованием C++

У VonC есть комментарий с ассемблерным кодом таймера ЦП.

Согласно вашему вопросу, каждые 30 мс вы хотите обновлять область просмотра.Однажды я написал похожее приложение, которое каждые 500 мс проверяло оборудование на предмет подобных вещей.Хотя это не дает прямого ответа на ваш вопрос, у меня есть следующие дополнения:

  • Вы уверены, что Blah() для обновления области просмотра может выполняться менее чем за 30 мс в каждом экземпляре?
  • Похоже, что запуск Blah() будет лучше с помощью обратного вызова таймера.
  • Очень сложно найти объект библиотечного таймера, который будет использовать интервал 30 мс для обновления графической среды.В Windows XP я обнаружил, что стандартный таймер API Win32, который отправляет оконные сообщения по истечении интервала таймера, даже на P4 с частотой 2 ГГц, не может выполнять обновления быстрее, чем с интервалом 300 мс, независимо от того, насколько низким я установил интервал времени на таймер.Несмотря на то, что в Win32 API доступны высокопроизводительные таймеры, у них есть много ограничений, а именно: вы не можете выполнять какие-либо IPC (например, обновлять виджеты пользовательского интерфейса) в цикле, подобном тому, который вы указали выше.
  • По сути, вы должны очень тщательно планировать, как вы хотите, чтобы обновления происходили.Возможно, вам придется использовать потоки и посмотреть, как вы хотите обновить область просмотра.

Просто есть о чем подумать.Они застали меня врасплох, когда я работал над своим проектом.Если вы уже все обдумали, пожалуйста, не обращайте внимания на мой ответ :0).

Вы можете просто обновлять область просмотра каждые N шагов моделирования, а не каждые K миллисекунд.Если это (скажем) серьезное коммерческое приложение, то вам, вероятно, захочется пойти по многопоточному маршруту, предложенному в другом месте, но если (скажем) оно предназначено для личного использования или использования ограниченной аудиторией и то, что вас действительно интересует. Это детали того, что вы моделируете, тогда каждые N шагов просты, портативны и вполне могут быть достаточно хороши, чтобы с ними можно было справиться.

См. QueryPerformanceCounter и QueryPerformanceFrequency.

Если вы используете Qt, вот простой способ сделать это:

QTimer* t = new QTimer( parent ) ;
t->setInterval( 30 ) ; // in msec
t->setSingleShot( false ) ;
connect( t, SIGNAL( timeout() ), viewPort, SLOT( redraw() ) ) ;

Вам нужно будет указать viewPort и redraw().Затем запустите таймер с t->start().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top