2009-06-22 5 views
1

Я хочу выполнить действие в определенный тайм-аут, например, пожар . Я выяснил, как делать каждое n секунд, но не 1.5 секунд. Вот что у меня есть. Пожалуйста, предложите, как обращаться мой случай:Выполнение операции с интервалом

void Publish() 
{ 
    static int local_time=time(NULL); 

    int current_time = time (NULL); 
    if((current_time+PUBLISH_TIMEOUT)>local_time) 
     { 
      fireEvent(); 
      local_time=current_time; 
     } 
} 
+0

Я удалил статику из «static int local_time», так как у нее не было много логики – fmsf

+2

почему бы и нет? Я только хочу инициализировать local_time один раз, а затем продолжить его обновление. Обратите внимание, что публикация вызывается все время – 2009-06-22 14:45:21

ответ

0

Это возвращает время стены с момента запуска приложения в миллисекундах. Он использует часы машин, поэтому вполне возможно, что изменение времени работы часов при запуске приложения смутит его. В вашем случае я хотел бы добавить запланированное время для моего объекта события и огонь, когда график времени < = Мс()

clock_t msec() { 
    static struct timeval msec_base; 
    struct timeval now; 

    long seconds, useconds; 
    if (!msec_base.tv_usec) 
     gettimeofday(&msec_base, NULL); 
    gettimeofday(&now, NULL); 

    seconds = now.tv_sec - msec_base.tv_sec; 
    useconds = now.tv_usec - msec_base.tv_usec; 

    return ((seconds) * 1000 + useconds/1000.0); 
} 
+0

После нескольких модификаций я сделал это для работы, особенно вам не нужно умножать секунды на 1000, и вам нужно удалить useconds на 10 000.0 Спасибо. – 2009-06-22 15:31:13

+0

, вы можете захотеть взглянуть на CLOCKS_PER_SEC http://www.cplusplus.com/reference/clibrary/ctime/CLOCKS_PER_SEC/ для решения этих проблем. –

1

gettimeofday() возвращает микросекунд, так что вы можете использовать его вместо time() - см определение struct timeval эта функция заполняет.

За дополнительной информацией обращайтесь к man gettimeofday.

+0

Если вы хотите поместить эту функцию в свой собственный поток и хотите добавить паузу, gettimeday() использует тот же тип (struct timeval), что и вызов select(). В зависимости от ваших обстоятельств select() может полностью заменить любые запросы времени. – Jamie

+0

@ Jamie Я согласен, но OP не просил паузы - если он/она, я предпочел бы предложить usleep() или даже nanosleep(), потому что nano-версия - POSIX. – qrdl

0

Комплексное решение на основе ответа Ник:

#include <sys/time.h> 
#include <iostream> 
#include <cstdlib> 

using namespace std; 

int TOTAL_PROCESSES; 
double TIMEOUT; 
int process() 
{ 

    static struct timeval msec_base; 
    struct timeval now; 

    long seconds, useconds; 
    if (!msec_base.tv_usec) 
     gettimeofday(&msec_base, NULL); 

    gettimeofday(&now, NULL); 

    seconds = now.tv_sec - msec_base.tv_sec; 
    useconds = now.tv_usec - msec_base.tv_usec; 

    double time_diff=seconds+ useconds/100000.0; 

    if(TIMEOUT < time_diff) 
    { 
     cout<<TIMEOUT <<" seconds...\n"; 
     msec_base=now; 

     return 1; 
    } 
    return 0; 

} 

int main(int argc, char** argv) 
{ 
    if(argc < 3) 
    { 
     cout<<"Error: missing TIMOUT and total time to fire\n"; 
     return -1; 

    } 

    TIMEOUT  = atof(argv[1]); 
    TIMES_TO_FIRE = atoi(argv[2]); 

    cout << "INFO: TIMEOUT="<<TIMEOUT<<", TIMES_TO_FIRE ="<< TIMES_TO_FIRE <<endl; 


    int i=0; 
    while (i< TIMES_TO_FIRE) 
     i+=process(); 

    return 0; 
} 
0

Вы можете использовать импульс: : ASIO для этого, обратитесь к документации здесь:

http://think-async.com/Asio/boost_asio_1_4_1/doc/html/boost_asio/reference/deadline_timer.html

+0

Я не думаю, что вы можете, так как мне нужен блокирующий блок NEVER, но пропустите выполнение до тех пор, пока не будет превышен тайм-аут. – 2009-06-22 15:38:35

0

Если это C, то почему бы не использовать setitimer() и SIGALRM?

Что такое setitimer(), с определенным интервалом (который вы можете указать до миллисекунды), он запускает сигнал SIGALRM. Затем вы можете настроить свою программу так, чтобы она имела функцию, которая реагирует на этот сигнал.

Функция alarm() выполняет то же самое, что и setitimer(), но alarm() работает только с интервалом в 1 секунду (не 1,5 секунды и т. Д.). Тем не менее, this page дает руководство по обработке прерывания , Используя этот метод, вы можете сэкономить много времени на вычисление кода.

+0

это не сработает, так как я хочу только позвонить, когда информация доступна, а время ожидания истекло. – 2009-06-22 19:13:21

+0

Ну, способы сделать эту работу могут быть: ваш код таймера должен будет проверить, доступна ли информация в момент установки SIGALRM. Или сделайте это с комбинацией отмены тревоги. – poundifdef

+0

Если вы хотите доли секунды, вы можете использовать nanosleep() –

0

Я знаю, что это не второй основе, но вы можете использовать регистр RDTSC в зависимости от вашего процессора ... Подробнее here (для измерения времени упущений в Linux)

0

@puzzlecracker

не является Процессор загружает беспокойство? Ваша процедура постоянно проверяет состояние на ненужное число раз. Я хотел бы использовать USleep(), когда он пропускает:

... 

if(TIMEOUT < time_diff) 
{ 
    cout<<TIMEOUT <<" seconds...\n"; 
    msec_base=now; 

    return 1; 
} else usleep(10); 

... 

На этот раз выхода для других процессов, и не дает какой-либо штраф вашего коду отзывчивости.

Еще лучшим решением было бы использовать clock_nanosleep() с другим подходом, подобным поточному таймеру.

+0

Я не могу блокировать, хотя я не могу публиковать. Мое приложение однопоточное и выполняет много коммутации, результаты которого публикуются с определенным интервалом. Вычисление никогда не останавливается. – 2009-06-23 19:06:45