本文介绍了定时器类在linux的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need a timer to execute callbacks with relatively low resolution. What's the best way to implement such C++ timer class in Linux? Are there any libraries I could use?

推荐答案

如果你在一个框架内编写(Glib,Qt,Wx,.. 。),你已经有一个带有定时回调函数的事件循环。

If you're writing within a framework (Glib, Qt, Wx, ...), you'll already have an event loop with timed callback functionalities. I'll assume that's not the case.

如果您正在编写自己的事件循环,可以使用 gettimeofday / 选择对( struct timeval ,微秒精度)或 clock_gettime / nanosleep 对( struct timespec ,nanosecond precision)即使后面的界面是更高的分辨率,调度从来不是那么准确,所以采取任何适当的最佳。

If you're writing your own event loop, you can use the gettimeofday/select pair (struct timeval, microsecond precision) or the clock_gettime/nanosleep pair (struct timespec, nanosecond precision) for your own event dispatcher. Even though latter interface is higher resolution, scheduling is never that accurate anyways, so take whatever fits best.

#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;
}



警告:我爱C.我从来不写C ++。我只是假装知道这种语言。

Warning: I love C. I never write C++. I'm just pretending to know the language.

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

Disclaimer: written just now and totally untested. The basic idea is to keep events in a priority queue, wait until the first one, run it, and repeat.

这篇关于定时器类在linux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 12:10