C++ linux中的定时器类

C++ linux中的定时器类,c++,linux,timer,C++,Linux,Timer,我需要一个计时器来执行分辨率相对较低的回调。在Linux中实现C++类定时器的最好方法是什么?有我可以使用的库吗?试试time.h中定义的clock_gettime()函数: int clock_gettime(clockid_t clk_id, struct timespec *tp); struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }

我需要一个计时器来执行分辨率相对较低的回调。在Linux中实现C++类定时器的最好方法是什么?有我可以使用的库吗?

试试time.h中定义的clock_gettime()函数:

int clock_gettime(clockid_t clk_id, struct timespec *tp);

struct timespec {
  time_t   tv_sec;        /* seconds */
  long     tv_nsec;       /* nanoseconds */
};
通常您可以这样称呼它:

struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);

使用boost::asio库。它具有调用回调的同步和异步计时器


您要查找的是time.h头中的timeval结构。它的时间单位是秒和纳秒。所以以纳秒为单位的总时间是timeval.tv_sec*1000000+timeval.tv_usec。我觉得很简单

#include <time.h>
timeval theStartTime;
gettimeofday(&theStartTime);
std::cout<<"The time we got's seconds field = "<<theStartTime.tv_sec<<std::endl;
std::cout<<"The time we got's nanoseconds field =  "<<theStartTime.tv_usec<<std::endl;
#包括
timeval开始时间;
gettimeofday(&开始时间);

如果您在一个框架(Glib、Qt、Wx等)中编写,那么您已经有了一个带有定时回调功能的事件循环。我想情况并非如此

如果您正在编写自己的事件循环,您可以使用
gettimeofday
/
select
对(
struct timeval
,微秒精度)或
clock\u gettime
/
nanosleep
对(
struct timespec
,纳秒精度)作为您自己的事件调度程序。尽管后一个界面的分辨率更高,但无论如何调度都不会那么精确,所以选择最合适的

#include <algorithm>
#include <functional>
#include <vector>

#include <errno.h>
#include <sys/time.h>
#include <unistd.h>

using namespace std;

class scheduler {
public:
    scheduler();
    int events();
    void addEvent(const struct timeval, int (*)(void *), void *);
    int dispatchUntil(const struct timeval &);
    bool waitUntil(const struct timeval * = NULL);
    int loopUntil(const struct timeval * = NULL);

private:
    static bool tv_le(const struct timeval &, const struct timeval &);
    struct event {
        struct timeval when;
        int (*callback)(void *);
        void *data;
    };
    static struct _cmp
      : public binary_function<bool, const struct event &, const struct event &>
    {
        bool operator()(const struct event &a, const struct event &b) {
            return !tv_le(a.when, b.when);
        }
    } cmp;
    vector<struct event> heap;
};

bool scheduler::tv_le(const struct timeval &a, const struct timeval &b) {
    return a.tv_sec < b.tv_sec ||
        a.tv_sec == b.tv_sec && a.tv_usec <= b.tv_usec;
}

scheduler::scheduler() : heap() {}

int scheduler::events() {
    return heap.size();
}

void scheduler::addEvent(const struct timeval when, int (*callback)(void *), void *data) {
    struct event ev = {when, callback, data};
    heap.push_back(ev);
    push_heap(heap.begin(), heap.end(), cmp);
}

int scheduler::dispatchUntil(const struct timeval &tv) {
    int count = 0;
    while (heap.size() > 0 && tv_le(heap.front().when, tv)) {
        struct event ev = heap.front();
        pop_heap(heap.begin(), heap.end(), cmp);
        heap.pop_back();
        ev.callback(ev.data);
        count++;
    }
    return count;
}

bool scheduler::waitUntil(const struct timeval *tv) {
    if (heap.size() > 0 && (!tv || tv_le(heap.front().when, *tv)))
        tv = &heap.front().when;
    if (!tv)
        return false;
    struct timeval tv2;
    do {
        gettimeofday(&tv2, NULL);
        if (tv_le(*tv, tv2))
            break;
        tv2.tv_sec -= tv->tv_sec;
        if ((tv2.tv_usec -= tv->tv_usec) < 0) {
            tv2.tv_sec--;
            tv2.tv_usec += 1000000;
        }
    } while (select(0, NULL, NULL, NULL, &tv2) < 0 && errno == EINTR);
    return heap.size() > 0 && tv_le(*tv, heap.front().when);
}

int scheduler::loopUntil(const struct timeval *tv) {
    int counter = 0;
    while (waitUntil(tv))
        counter += dispatchUntil(heap.front().when);
    return counter;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
类调度程序{
公众:
调度程序();
int事件();
void addEvent(const struct timeval,int(*)(void*),void*);
int dispatchUntil(const struct timeval&);
bool waitill(const struct timeval*=NULL);
int loopUntil(const struct timeval*=NULL);
私人:
静态布尔电视(const-struct-timeval&,const-struct-timeval&);
结构事件{
结构timeval时;
int(*回调)(无效*);
作废*数据;
};
静态结构
:公共二进制函数
{
布尔运算符()(常量结构事件&a、常量结构事件&b){
return!tv_le(a.when,b.when);
}
}化学机械抛光;
向量堆;
};
bool调度程序::tv_le(const struct timeval&a、const struct timeval&b){
返回a.tv秒0&(!tv | | tv| le(heap.front().when,*tv)))
tv=&heap.front().when;
如果(!电视)
返回false;
结构时间值tv2;
做{
gettimeofday(&tv2,NULL);
中频(电视(*tv,tv2))
打破
tv2.tv_sec-=tv->tv_sec;
如果((tv2.tv\u usec-=tv->tv\u usec)<0){
tv2.tv_第二节;
tv2.tv_usec+=1000000;
}
}while(选择(0,NULL,NULL,NULL,&tv2)<0&&errno==EINTR);
返回heap.size()>0&&tv_le(*tv,heap.front().when);
}
int调度程序::loopUntil(const struct timeval*tv){
int计数器=0;
while(waitill(电视))
计数器+=dispatchUntil(heap.front().when);
返回计数器;
}
警告:我喜欢C。我从来不写C++。我只是假装懂这门语言


免责声明:刚刚编写,完全未经测试。基本思想是将事件保持在优先级队列中,等待第一个事件,运行它,然后重复。

这里是计时器类的链接。u将只需要创建计时器并将其值传递给自动重新加载或不自动重新加载。指向回调函数的指针。如果你想让它由线程或信号处理。如果你选择信号,那么你也必须通过信号


如果你想学习更多关于定时器或信号的知识,有一本叫做linux系统编程的好书。你只需阅读3章,并解释所有内容。

什么是相对较低的分辨率?哈哈,洛基。当我读到他的问题时,数百毫秒到秒Hanks@Jack,为了提问,我正在寻找相同的功能,并为我节省了很多时间,SOF rocks\m/。对不起,我指的是一个计时器,可以在指定的时间间隔后注册要启动的回调。对不起,但我指的是一个计时器,可以在指定的时间间隔后注册要启动的回调。