Как создать эффективный портативный таймер в C ++? - PullRequest
2 голосов
/ 14 декабря 2011

Для школьного проекта мне нужно (заново) создать полнофункциональную многопользовательскую версию R-Type без использования следующих внешних библиотек:

  • Повышение
  • SFML / SDL
  • Qt
  • Использование C ++ 11 запрещено

Кроме того, эта игра должна быть полностью переносимой между Fedora (Linux) и Windows. Я отвечаю за сервер, поэтому использование любых графических библиотек строго запрещено.

Чтобы создать правильный игровой цикл, мне нужен правильный класс Timer, подобный классу, найденному в SDL, который реализует методы GetTicks () или GetElapsedTime (). Но я спросил себя, что было бы лучшим способом создать такой класс, но пока я начинаю так:

  • Создание поточного класса с использованием pthread (который является переносимым)
  • Использование функций time () и difftime () в цикле, чтобы определить, сколько времени прошло с момента последнего тика.

Зная, что этот класс будет использоваться десятками одновременно играющих экземпляров, должен ли я использовать Singleton Design Pattern? Будут ли эти методы точными?

РЕДАКТИРОВАТЬ: Изменено объяснение моего вопроса, чтобы больше соответствовать моим потребностям и быть более точным в том, что мне разрешено использовать или нет.

Ответы [ 4 ]

2 голосов
/ 14 декабря 2011

Нет простого способа сделать то, что ты думаешь. К счастью, есть простые способы сделать то, что вы хотите.

Первый: Using the functions time() and difftime() in a loop to determine how much time was elapsed Это ужасная идея. Это будет использовать 100% одного из ваших процессоров и тем самым замедлит вашу программу для сканирования. Если вы хотите подождать определенное время («тик» 1/60 секунды или 1/10 секунды), просто подождите. Не крути нить.

Заголовок:

long long get_time();
long long get_freq();
void wait_for(long long nanoseconds);

касты:

#ifdef _MSC_VER //windows compiler for windows machines
long long get_time() {
    LARGE_INTEGER r;
    QueryPerformanceCounter(r);
    return r.QuadPart;
}
long long get_freq() {
    LARGE_INTEGER r;
    QueryPerformanceFrequency(r);
    return r.QuadPart;
}
void wait_for(long long nanoseconds)
{
    Sleep(nanoseconds / 1000000);
}
#endif
#ifdef __GNUC__ //linux compiler for linux machines
long long get_time() {
    timespec r
    clock_gettime(CLOCK_MONOTONIC, &r);
    return long long(r.seconds)*1000000000 + r.nanoseconds;
}
long long get_freq() {
    timespec r
    clock_getres(CLOCK_MONOTONIC, &r);
    return r.nanoseconds;
}
void wait_for(long long nanoseconds)
{
    timespec r = {nanoseconds/1000000000, nanoseconds%1000000000};
    nanosleep(&r, NULL);
}
#endif

Ничто из этого не идеально (тем более, что я не пишу код для Linux), но это общая концепция, когда вам приходится иметь дело с ОС (поскольку она не входит в стандартную комплектацию, и вы не можете использовать библиотеки). Реализации Windows и GCC могут быть в отдельных файлах, если вам нравится

1 голос
/ 14 декабря 2011

Учитывая, что спецификации отсутствуют, не будут работать на окнах, не включенных в стандарт.

Если вы можете использовать C ++ 11, вы можете использовать std :: chrono для таймера, это высокоточный таймер с довольно интуитивным интерфейсом. Он был в основном снят с boost (как и с thread), поэтому большая часть документации по boost переведена на std :: chrono. (или для низкой точности просто используйте библиотеку времени C), а для потоков вы можете использовать std :: thread.

N.B. эти элементы стандартной библиотеки, и вы просто создаете тест на своих платформах, чтобы убедиться, что используемый вами stdlib поддерживает их (вам нужно включить c ++ 11 - обычно --std = c ++ 0x)

Я точно знаю, что gcc 4.6 имеет большинство потоков и хронографов и кажется стабильным.

0 голосов
/ 14 декабря 2011

Чтобы получить время на стене, вы можете использовать QueryPerformanceCounter в Windows и clock_gettime() с CLOCK_MONOTONIC в системах POSIX (CLOCK_MONOTONIC_RAW Linux 2.6.28 +).

0 голосов
/ 14 декабря 2011

Возможно, вы захотите создать оболочку около gettimeofday для Linux, которая возвращает количество микросекунд с начала эпохи, и GetTickCount для Windows, которая возвращает количество миллисекунд с момента запуска системы.

Вы также можете использовать clock () в Windows, который будет возвращать секунды * CLOCKS_PER_SEC (да, время настенных часов, а не процессорное время) с момента запуска процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...