服務器設計筆記(1)-----定時器的實現(C++)
很久之前聽著名頁遊服務器主程講座時,講到過定時器的實現,基本思路如下(易語言)
while(true)
{
對定時器進行排序。
for(遍曆定時器)
{
if 如果定時器到:
callback;
else
break;
}
usleep(20);
}
按照這個思路,我們繼續我們的設計:
1: 首先 定義一個Thread類:
/*
* 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,
};
public:
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_ */
* 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,
};
public:
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_ */
實現代碼Thread.cpp:

/*
* Thread.cpp
*
* Created on: Sep 11, 2012
* Author: root
*/
#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);
return 0;
}
* Thread.cpp
*
* Created on: Sep 11, 2012
* Author: root
*/
#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);
return 0;
}
2:定義定時器,和定時器線程:
TimerThread.h
/*
* Timer.h
*
* Created on: Sep 11, 2012
* Author: root
*/
#ifndef TIMER_H_
#define TIMER_H_
#include "Thread.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
{
public:
static TimerThread* _instance;
static TimerThread* get_instance();
virtual void* run(void);
virtual ~TimerThread();
void Register(Timer _timer);
void unRegister(Timer _timer);
private:
TimerThread();
list<Timer> _timer_list;
};
extern unsigned int get_systime_clock();
#define TIMERMANAGE TimerThread::get_instance()
#endif /* TIMER_H_ */
* Timer.h
*
* Created on: Sep 11, 2012
* Author: root
*/
#ifndef TIMER_H_
#define TIMER_H_
#include "Thread.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
{
public:
static TimerThread* _instance;
static TimerThread* get_instance();
virtual void* run(void);
virtual ~TimerThread();
void Register(Timer _timer);
void unRegister(Timer _timer);
private:
TimerThread();
list<Timer> _timer_list;
};
extern unsigned int get_systime_clock();
#define TIMERMANAGE TimerThread::get_instance()
#endif /* TIMER_H_ */
實現代碼:TimerThread.cpp

/*
* Timer.cpp
*
* Created on: Sep 11, 2012
* Author: root
*/
#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;
}
* Timer.cpp
*
* Created on: Sep 11, 2012
* Author: root
*/
#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;
}
3: 測試函數:

//============================================================================
// 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>
#include "Timer.h"
using namespace std;
int handle_timeout()
{
unsigned int time = get_systime_clock();
printf("time out,%u\n",time);
return 0;
}
int main()
{
Timer _timer;
_timer.open(1,handle_timeout);
TIMERMANAGE->Register(_timer);
TIMERMANAGE->start();
getchar();
return 0;
}
// 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>
#include "Timer.h"
using namespace std;
int handle_timeout()
{
unsigned int time = get_systime_clock();
printf("time out,%u\n",time);
return 0;
}
int main()
{
Timer _timer;
_timer.open(1,handle_timeout);
TIMERMANAGE->Register(_timer);
TIMERMANAGE->start();
getchar();
return 0;
}
目前存在的問題:定時不準,主要是由於usleep()之後 ,不能及時醒,這個是因為Linux線程調度引起的。
改進的方向:1. TimerThread 裏麵的list換成優先隊列
2. 添加時間糾正,在測試中發現,每次大概慢100us左右,這對於長時間的定時器是致命。
也想聽聽廣大網友的意見,感激不盡。
最後更新:2017-04-02 15:28:25
上一篇:
係統架構評估
下一篇:
分布式數據庫
阿裏巴巴將與西安交通大學共建大數據學院
《Spring Data官方文檔》5.3. Connecting to Cassandra with Spring至5.5. Introduction to CassandraTemplate
iphone6怎麼刷機解鎖密碼 iphone6開機密碼忘了怎麼解鎖
拉格朗日乘數法
H5???????????????????????????????????????-??????-????????????-?????????
getCurrentSession與openSession的區別
兩屆CVPR最佳論文得主何愷明新作:應對樣本的不平衡分布,刷新密集物體檢測表現上限
為什麼有時候讀取文件,atime不更新
阿裏雲大數據開發套件 新手不得不麵對的問題(持續更新)
感謝現實殘酷,才讓我勇敢選擇遠程工作