2013-03-17 76 views
4

任務是每x(例如x = 10)秒執行一個函數(比如Processfunction())。以特定間隔執行功能

使用以下代碼,我可以每x秒呼叫Processfunction()

問題:如何處理功能需要超過10秒才能完成執行的情況?

一種方法是在調用Processfunction()之前有一個標誌來指示Processfunction()結束執行並檢查它。 有沒有更好的方法來做到這一點?


#include <pthread.h> 
#include <unistd.h> // for sleep() and usleep() 

void *timerthread(void *timer_parms) { 

    struct itimerspec new_value; 
    int max_exp, fd; 
    struct timespec now; 
    uint64_t exp; 
    ssize_t s; 

    struct timer_params *p =(struct timer_params*)timer_parms; 

    printf("starttimer Start\n"); 
    /* Create a CLOCK_REALTIME absolute timer with initial 
    expiration and interval as specified in command line */ 
    if (clock_gettime(CLOCK_REALTIME, &now) == -1) 
    handle_error("clock_gettime"); 

    new_value.it_value.tv_sec = now.tv_sec; 
    new_value.it_value.tv_nsec = now.tv_nsec + p->tv_nsec; 
    new_value.it_interval.tv_sec = p->tv_sec; 
    new_value.it_interval.tv_nsec = p->tv_nsec; 
    //max_exp = 5; //No of times 

    fd = timerfd_create(CLOCK_REALTIME , 0); 
    if (fd == -1) 
    handle_error("timerfd_create"); 

    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1) 
    handle_error("timerfd_settime"); 

    printf("timer started\n"); 

    while(1) // keep checking 
    { 
    s = read(fd, &exp, sizeof(uint64_t)); 
    if (s != sizeof(uint64_t)) 
     handle_error("read"); 
    Processfunction(); // Say after X seconds call this function 
    } 
    return NULL; 
} 

int main() { 

    struct timer_params timer_params_obj; 
    int res;void *thread_result; 
    timer_params_obj.tv_sec = 10; 
    //timer_params_obj.tv_nsec = 10000000 ; //10ms 
    timer_params_obj.tv_nsec = 0 ; 

    pthread_t pt; 
    pthread_create(&pt, NULL, timerthread, &timer_params_obj); 
    // thread is running and will call Processfunction() every 10 sec 
} 
+0

你不想有兩個'Processfunction()'同時運行嗎?如果執行時間長於通常允許的間隔持續時間,您是否希望延遲調用或跳過調用? – moooeeeep 2013-03-17 18:45:06

+0

是的,我不希望它在同一時間運行。我想跳過/延遲更長的執行時間。 – m4n07 2013-03-19 15:05:06

回答

4

爲什麼你需要爲這個定時器嗎?

您可以根據經過時間與期望間隔持續時間的關係來測量執行時間並進行睡眠。

實施例:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <unistd.h> 

int main() { 
    srand(1); 
    for (;;) { 
     double interval = 10; /* seconds */ 

     /* start time */ 
     time_t start = time(NULL); 

     /* do something */ 
     int duration = rand() % 13; 
     printf("%2d seconds of work started at %s", duration, ctime(&start)); 
     sleep(duration); 

     /* end time */ 
     time_t end = time(NULL); 

     /* compute remaining time to sleep and sleep */ 
     double elapsed = difftime(end, start); 
     int seconds_to_sleep = (int)(interval - elapsed); 
     if (seconds_to_sleep > 0) { /* don't sleep if we're already late */ 
      sleep(seconds_to_sleep); 
     } 
    } 
    return 0; 
} 

輸出:

$ gcc test.c && ./a.out 
0 seconds of work started at Sun Mar 17 21:20:28 2013 
9 seconds of work started at Sun Mar 17 21:20:38 2013 
11 seconds of work started at Sun Mar 17 21:20:48 2013 
4 seconds of work started at Sun Mar 17 21:20:59 2013 
1 seconds of work started at Sun Mar 17 21:21:09 2013 
^C 
+0

+1 - 是的 - 我就是這麼做的。定時器經常被不恰當地使用:( – 2013-03-19 12:19:27

+0

這可以在沒有linux特定代碼(boost或C++ 11)的情況下完成,而且沒有睡眠?程序還有其他的事情需要處理 – 2015-07-30 02:16:28

+0

@AndrewHundt你可以使用Boost.Asio的最後期限定時器以異步等待特定的時間由於異步程序流,你可能需要重構你的代碼(如果事實並非如此) – moooeeeep 2015-08-05 11:41:00

1

我有除我需要它是跨平臺的C++ 11和執行其他任務在此期間需要一個幾乎相同的情況下,使用而不是睡覺。這裏是我的情況下,代碼是有用的人:

#include <iostream> 
#include <chrono> 

/// Tracks the time since execution() was called, and only 
/// Calls the passed function if the minimum time interval has elapsed 
/// @see https://stackoverflow.com/questions/2808398/easily-measure-elapsed-time for the code I based this on 
template<typename TimeT = std::chrono::milliseconds> 
struct periodic 
{ 
    periodic(TimeT duration = TimeT(1)): 
    start(std::chrono::system_clock::now()), 
    period_duration(duration), 
    previous_duration(TimeT::zero()) 
    {}; 

    template<typename F, typename ...Args> 
    TimeT execution(F func, Args&&... args) 
    { 
     auto duration = std::chrono::duration_cast< TimeT> 
          (std::chrono::system_clock::now() - start); 
     if(duration > previous_duration + period_duration) 
     { 
      std::forward<decltype(func)>(func)(std::forward<Args>(args)...); 
      previous_duration = duration; 
     } 
     return duration; 
    } 

    std::chrono::time_point<std::chrono::system_clock> start; 
    // The minimum duration to wait before the function can be called again 
    TimeT period_duration; 
    // The duration between startup and the last time the function was called 
    TimeT previous_duration; 
}; 

下面是使用它的一個例子:

int main(int argc, char* argv[]) 
{ 

    periodic<> callIfMinPeriodPassed(std::chrono::milliseconds(1)); 
    std::size_t num_periods; 

    while(true) 
    { 
      callIfMinPeriodPassed.execution([&num_periods]() 
      { 
        std::cout << ++num_periods << "timesteps have passed\n" 
      }); 
      // do other stuff here, this example will work 
      // but spins at 100% CPU without the sleep 
      std::this_thread::sleep_for(std::chrono::milliseconds(1)); 
    } 

} 

這個實現是基於this stackoverflow question about measuring elapsed time修改。