2009-02-02 52 views
2

我需要一個定時器來執行分辨率相對較低的回調。在Linux中實現這種C++定時器類的最佳方式是什麼?有我可以使用的任何圖書館嗎?linux中的計時器類

+0

什麼是相對較低的分辨率? – Loki 2009-02-02 18:12:02

+0

哈哈,洛基。正是我想當我讀他的問題 – 2009-02-03 03:53:08

+0

數百毫秒到秒 – jackhab 2009-02-03 08:11:25

回答

14

如果你的框架(油腔滑調,Qt的,蠟質,...)內以書面形式,你已經有一個事件循環與定時回調功能。我會認爲情況並非如此。

如果你正在寫自己的事件循環,可以使用gettimeofday/select對(struct timeval,微秒級精度)或clock_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; 
} 

警告:我愛C.我從來沒有寫C++。我只是假裝知道這門語言。

免責聲明:剛剛寫完,完全沒有經過測試。基本思想是將事件保存在優先隊列中,等到第一個隊列,運行並重復。

0

嘗試clock_gettime()函數,在time.h中定義:

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); 
0

從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; 
0

這裏是定時器類的鏈接。你只需要創建計時器並將其傳遞給自動重裝或不重裝。一個指向回調函數的指針。或者如果你想要它由線程或信號處理。如果你選擇信號,那麼你也必須通過signo。

http://timerlinux.codeplex.com/

如果妳想要學習更多關於定時器或信號有一個很好的書叫做linux系統編程。你只需要閱讀3章並解釋它。