2013-03-17 104 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修改。