很久之前聽著名頁遊伺服器主程講座時,講到過定時器的實作,基本思路如下(易語言)
while(true)
{
對定時器進行排序。
for(周遊定時器)
{
if 如果定時器到:
callback;
else
break;
}
usleep(20);
}
按照這個思路,我們繼續我們的設計:
1: 首先 定義一個thread類:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
/*
* thread.h
*
* created on: sep 11, 2012
* author: root
*/
#ifndef thread_h_
#define thread_h_
#include <pthread.h>
class thread {
public:
enum threadstate
{
idle,
work,
busy,
};
thread();
virtual ~thread();
virtual void* run(void) = 0;
virtual int start(void);
virtual int cancel(void);
pthread_t get_pid() const
return pid;
}
protected:
threadstate _thread_state;
private:
pthread_t pid;
static void* thread_entry(void* para);
};
#endif /* thread_h_ */
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
實作代碼thread.cpp:
view
code
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
* thread.cpp
#include "thread.h"
thread::thread() {
// todo auto-generated constructor stub
}
thread::~thread() {
// todo auto-generated destructor stub
void* thread::thread_entry(void* para)
{
thread *pthread = static_cast<thread *>(para);
return pthread->run();
int thread::start(void)
if(pthread_create(&pid,0,thread_entry,static_cast<void *>(this)) < 0)
pthread_detach(this->pid);
return -1;
return 0;
int thread::cancel(void)
pthread_cancel(this->pid);
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
2:定義定時器,和定時器線程:
timerthread.h
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
* timer.h
#ifndef timer_h_
#define timer_h_
#include <list>
using namespace std;
struct timer
void *_args;
int (*_callback)();
int _interval;
int leftsecs;
void open(int interval,int (*callback)())
_interval = interval * 1000;
leftsecs = _interval;
_callback = callback;
bool operator < (timer _timer)
return _timer.leftsecs < this->leftsecs;
bool operator == (timer _timer)
return _timer.leftsecs == this->leftsecs;
class timerthread : public thread
static timerthread* _instance;
static timerthread* get_instance();
virtual void* run(void);
virtual ~timerthread();
void register(timer _timer);
void unregister(timer _timer);
timerthread();
list<timer> _timer_list;
extern unsigned int get_systime_clock();
#define timermanage timerthread::get_instance()
#endif /* timer_h_ */
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
實作代碼:timerthread.cpp
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
* timer.cpp
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "timer.h"
timerthread* timerthread::_instance;
timerthread::timerthread()
timerthread::~timerthread()
void* timerthread::run(void)
while(true)
unsigned int start_clock = get_systime_clock();
this->_timer_list.sort();
list<timer>::iterator iter;
for(iter = this->_timer_list.begin();
iter != this->_timer_list.end();
iter ++)
{
iter->leftsecs --;
if(iter->leftsecs == 0)
{
iter->_callback();
iter->leftsecs = iter->_interval;
}
}
unsigned int end_clock = get_systime_clock();
usleep(1000 + start_clock - end_clock);
return (void*)0;
void timerthread::register(timer _timer)
this->_timer_list.push_back(_timer);
void timerthread::unregister(timer _timer)
this->_timer_list.remove(_timer);
timerthread* timerthread::get_instance()
if(_instance == null)
_instance = new timerthread();
return _instance;
unsigned int get_systime_clock()
struct timeval now;
gettimeofday(&now,null);
return now.tv_sec*1000 + now.tv_usec/1000;
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
3: 測試函數:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
//============================================================================
// name : test.cpp
// author : archy
// version :
// copyright : your copyright notice
// description : hello world in c++, ansi-style
#include <iostream>
#include <string>
#include <stdio.h>
#include <sys/types.h>
int handle_timeout()
unsigned int time = get_systime_clock();
printf("time out,%u\n",time);
int main()
timer _timer;
_timer.open(1,handle_timeout);
timermanage->register(_timer);
timermanage->start();
getchar();
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
目前存在的問題:定時不準,主要是由于usleep()之後 ,不能及時醒,這個是因為linux線程排程引起的。
改進的方向:1. timerthread 裡面的list換成優先隊列
2. 添加時間糾正,在測試中發現,每次大概慢100us左右,這對于長時間的定時器是緻命。
也想聽聽廣大網友的意見,感激不盡。