閱讀1008 返回首頁    go 阿裏雲 go 技術社區[雲棲]


服務器設計筆記(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.cpp:

View Code
複製代碼
/*
 * 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_ */
複製代碼

 

          實現代碼:TimerThread.cpp

View Code
複製代碼
/*
 * 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: 測試函數:

View Code
複製代碼
//============================================================================
// 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

  上一篇:go 係統架構評估
  下一篇:go 分布式數據庫