如何在C ++中创建高效的便携式计时器?

时间:2011-12-13 21:32:23

标签: c++ windows linux

对于一个学校项目,我需要(重新)创建一个功能齐全的R-Type多人版本,而不使用以下外部库:

  • 升压
  • SFML / SDL
  • Qt的
  • 不允许使用C ++ 11

此外,这款游戏必须在Fedora(Linux)和Windows之间完全可移植。我负责服务器,因此严禁使用任何图形库。

为了创建正确的游戏循环,我需要一个正确的Timer类,类似于SDL中实现的GetTicks()或GetElapsedTime()方法。但是我问自己创建这样一个Class的最佳方法是什么,到目前为止我就是这样开始的:

  • 使用pthread(可移植)创建线程类
  • 在循环中使用函数time()和difftime()来确定自上次滴答以来经过的时间。

知道这个类会被几十个同时播放的实例使用,我应该使用Singleton设计模式吗?这种方法准确吗?

编辑:更改了我的问题的解释,以满足我的更多需求,并更准确地说明我可以使用与否。

4 个答案:

答案 0 :(得分:2)

没有一种简单的方法可以做你想的事情。幸运的是,有很多方法可以做你想做的事。

首先:Using the functions time() and difftime() in a loop to determine how much time was elapsed这是一个糟糕的主意。这将使用100%的一个CPU,从而减慢程序的速度。如果你想等一段特定的时间(“滴答”1/60秒,或1/10秒),那就等一下。不要旋转线程。

头:

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

CPP:

#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 :(得分:1)

鉴于规格pthread已经出来,不会在Windows上运行,不包括在标准中。

如果你可以使用C ++ 11,你可以使用std :: chrono作为计时器,这是一个高精度计时器,具有相当直观的界面。它已经基本上从boost中提升了(因为有线程),所以boost的大部分文档都转换为std :: chrono。 (或者对于低精度只使用C时间库),对于线程,你可以使用std :: thread。

N.B。标准库的这些元素,您只需在平台上创建测试,以确保您使用的stdlib支持它们(您需要启用c ++ 11 - 通常是--std = c ++ 0x)

我确信gcc 4.6拥有大部分的线程和计时器并且看起来很稳定。

答案 2 :(得分:0)

您可能希望为Linux创建gettimeofday的包装器,它返回自Epoch以来的微秒数,以及Windows的GetTickCount,它返回自系统启动以来的毫秒数。

您也可以在Windows上使用clock(),这将在流程开始后返回秒* CLOCKS_PER_SEC(是的,挂钟时间而不是CPU时间)。

答案 3 :(得分:0)

要获得时间,您可以在Windows上使用QueryPerformanceCounter,在POSIX系统上使用clock_gettime() CLOCK_MONOTONICCLOCK_MONOTONIC_RAW Linux 2.6.28 +)。