gettimeofday возвращает отрицательное значение

Я пишу библиотеку потоков, и при планировании потоков мне нужно знать, как долго они были готовы. Каждый экземпляр потока имеет timeval _timeInReady поле, и когда я помещаю экземпляр в готовую очередь, я вызываю эту функцию:

void Thread::startTiming() {
    gettimeofday(&_timeInReady, NULL);
}

Когда я хочу проверить текущий _timeInReady значение я называю:

double Thread::getTimeInReady() const {
    return TIME(_timeInReady.tv_sec,_timeInReady.tv_usec);
}

Где ВРЕМЯ #define TIME(a,b) ((a*1000000) + b) Так что я получаю общее время в микросекундах.

Моя проблема в том, что по какой-то причине я получаю сумасшедшие отрицательные значения (например, -10293843), когда проверяю это поле через некоторое время.

Есть идеи? Спасибо!

3 ответа

Решение

Вы должны вернуть результат в виде 64-разрядного целого числа без знака, так как вы хотите получить целочисленный результат в микросекундах, а не дробную секунду (что подразумевает возврат double):

unsigned long long Thread::getTimeInReady() const
{
    return (unsigned long long)_timeInReady.tv_sec * 1000000ULL +
        (unsigned long long)_timeInReady.tv_usec;
}

Ваша система может иметь uint64_t который является более кратким, чем unsigned long longили вы могли бы typedef Это.

На моем компьютере все tv_sec, tv_usec, а также 1000000 подписаны 32-битные количества. 32-битные значения со знаком переполняются, когда их просят сохранить число больше 2^31 или около того.

В результате это выражение:

((x.tv_sec*1000000) + x.tv_usec)

переполнится в 2^31 / 10^6 секунд или около 2147 секунд. Пока ваша программа работает только с интервалами менее 35 минут, все будет в порядке.

Если вы хотите представить значения>= 35 минут, попробуйте заменить #define с этим:

#define TIME(a,b) ((a*1000000ull) + b)

Благодаря стандартным акциям это изменение приведет к выполнению всех ваших математических заданий с unsigned long long ценности.

Вы можете, но не обязательно, менять свой double в uint64_t, Это зависит от вас.

Попробуйте это, чтобы получить время для 32-битных систем:-

struct timeval time;
gettimeofday(&time, NULL);
unsigned long long secTime = ((unsigned long long)time.tv_sec) * 1000 + ((unsigned long long)(time.tv_usec))/1000;
Другие вопросы по тегам