【问题标题】:Hi-res Program Time高分辨率节目时间
【发布时间】:2012-08-19 17:33:06
【问题描述】:

我目前正在用 C++ 编写俄罗斯方块。现在我已经完成了程序编写的阶段,但我仍然需要修复一些错误并优化性能。

话虽如此,我的程序中的一个缺陷是它每秒只能处理一次按键。我需要它来处理至少三个。你可以看到这段代码展示的缺陷:

//Most headers only pertain to my main program.
#include <iostream>
#include <termios.h>
#include <pthread.h>
#include <time.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

using namespace std;

//Timer function.
void *Timer(void*) {

    time_t time1, time2;

    time1 = time(NULL);

    while (time2 - time1 < 1) {
        time2 = time(NULL);
    }

    pthread_exit(NULL);
}

int main() {

    //Remove canonical buffering.
    struct termios t_old, t_new;
    tcgetattr(STDIN_FILENO, &t_old);
    t_new = t_old;
    t_new.c_lflag &= (~ICANON & ~ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &t_new);

    const int STDIN = 0;

    struct timeval tv, tv1;
    fd_set readfds, readfds2, master;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    FD_ZERO(&readfds);
    FD_ZERO(&master);    
    FD_SET(STDIN, &readfds);
    FD_SET(STDIN, &master);
    char buffer[1];

    while(buffer[0] != 'q') {

        pthread_t inputTimer;

        pthread_create(&inputTimer, NULL, Timer, NULL);

        readfds = master;

        memcpy(&tv1, &tv, sizeof(tv));

        if (select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) {
            perror("select");
        }
        if (FD_ISSET(STDIN, &readfds)) {
            buffer[0] = cin.get();
            cout << "You entered: " << buffer << endl;

        }

        pthread_join(inputTimer, NULL);


        cout << "Timed out.\n" << endl;

    }

    cout << "Game Over." << endl;

    return 0;

}

如您所见,程序通过设置一秒间隔计时器和 timeval 来运行。因为两个计时器都使用整数来确定已经过去了多少时间,所以它们的精确度不能超过一秒。我怎样才能修改我的程序更精确?

我的想法是,如果按下某个键,则将tv1 的值复制到第三个值,然后再次等待输入,但不管tv1 是什么值时间。例如,如果我在只剩半秒时按下一个键,则值 0.5 将从 tv1 中获取并复制到另一个变量中。然后程序将只等待半秒的输入,而不是一整秒。然而,这不起作用,因为tv1 永远只等于10

【问题讨论】:

    标签: c++ time precision


    【解决方案1】:

    尝试使用struct timevalgettimeofday() in sys/time.h。您可以达到微秒级的分辨率。

    手册页:http://linux.die.net/man/3/gettimeofday

    更多信息:http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html

    编辑: 在 Linux(Windows 下不能移植到 MinGW)中,您还可以使用 poll()(参见 here),它可以让您等待几毫秒。这样会更有效率,因为poll 会暂停线程执行,直到超时。

    //Timer function.
    void *Timer(void*) {
        poll(0, 0, 100); //Suspend thread for 100 ms. 
        pthread_exit(NULL);
    }
    

    poll函数在poll.h中声明

    【讨论】:

      【解决方案2】:

      这里的问题是pthread_join 挂起主线程,直到定时器线程完成。因此,您将错过在加入期间或之后出现的任何用户输入。由于您已经在使用select,您不妨利用select 语句中内置的超时。如果你观察时间过去,你可以在没有定时器线程的情况下达到同样的效果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-17
        • 1970-01-01
        • 2012-12-21
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多