青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

那誰的技術(shù)博客

感興趣領(lǐng)域:高性能服務(wù)器編程,存儲,算法,Linux內(nèi)核
隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
數(shù)據(jù)加載中……

服務(wù)器公共庫開發(fā)--定時器管理器模塊

在寫定時器管理器時,參考了幾篇博文:
1)【原創(chuàng)】技術(shù)系列之 定時器(一)
2) libevent 源碼分析:min_heap帶來的超時機制

最后決定采用<<用TCP/IP進行網(wǎng)際互連>>第二卷中講述TCP定時器一章中的策略, 使用一個定時器鏈表, 根據(jù)定時器觸發(fā)的時間的升序排列, 每個定時器中有一個字段存放距離鏈表中上一個定時器觸發(fā)之后的相對時間值.這樣, 每次定時器到時的時候, 都去查詢定時器鏈表的第一個節(jié)點, 如果沒有到觸發(fā)時間就直接返回;否則就依次遍歷該鏈表, 查看哪些定時器是可以觸發(fā)的, 觸發(fā)定時器事件之后將這些定時器從鏈表中取出, 然后重新插入到定時器鏈表中, 并且更新相對時間字段.這個實現(xiàn)想法很簡單,但是實現(xiàn)的時候有不少細節(jié)需要考慮,我折騰了兩天在調(diào)試!!-_-.

另外,這個定時器管理器也是一個單件.

我的這個實現(xiàn)還是有局限性的:
1) 每個定時器有一個ID, 定時器與ID一一對應(yīng), 在定時器中有一個字段保存當前分配的ID計數(shù), 每新增一個定時器就加一, 但是刪除定時器卻不回收.這個字段是int型, 我想應(yīng)該沒有哪個系統(tǒng)會加入這么多定時器以至于溢出吧.
2) 采用setitimer進行定時, 每次觸發(fā)生成ALARM信號, 這要求在使用這個定時器的時候注意處理被信號中斷的情況(比如收發(fā)網(wǎng)絡(luò)數(shù)據(jù)時).在參考的第一篇博文中, 采用的是生成一個新的線程, 專門處理定時操作, 使用的是select函數(shù), 但是我認為如果這樣的話, 那么就用在代碼中注意多線程安全,這對于我這種基本不寫多線程服務(wù)器的人來說是個噩夢....
3)目前只做到精確到秒,不過,對我來說也夠用了.

timermanager.h:
/********************************************************************
    created:    2008/08/10
    filename:     timermanager.h
    author:        Lichuang
                
    purpose:    定時器管理器
********************************************************************
*/

#ifndef __TIMER_MANAGER_H__
#define __TIMER_MANAGER_H__

#include 
"singleton.h"
#include 
"threadmutex.h"
#include 
<map>
#include 
<list>
#include 
<signal.h>

using namespace std;

enum ETimeEventType
{
    TIMER_ONCE 
= 0,             //一次型
    TIMER_CIRCLE                //循環(huán)型
};

struct TTimeEvent
{
    
int nId;                    // 定時器ID
    int nInterval;              // 定時器時間間隔(秒)
    int nSecondsLeft;           // 相對定時器鏈表中前一個節(jié)點觸發(fā)后的相對時間(秒)
    ETimeEventType nType;       // 事件類型
    void (*pFn)(void* pArg);    // 回調(diào)函數(shù)
    void* pArg;                 // 回調(diào)函數(shù)參數(shù)
};

class CTimerManager
    : 
public CSingleton<CTimerManager>
{
public:
    
int Init(int nInterval);

    
int AddTimer(TTimeEvent& tTimeEvent);
    
int DelTimer(int nId);

    
void PrintTimerList();

    
int Start();
    
int Stop();

    
int Process();
private:
    CTimerManager();
    
virtual ~CTimerManager();

private:
    
int SetTimer(sighandler_t pFn);
    
int AddTimer(list<TTimeEvent>::iterator& tPos, TTimeEvent& tTimeEvent, bool bIsNewEvent);

private:
    
int m_nInterval;        
    unsigned 
int m_nIdCount;
    list
<TTimeEvent> m_lEvent;

    DECLARE_SINGLETON_CLASS(CTimerManager)    
};

#endif /* __TIMER_MANAGER_H__ */



timermanager.cpp:
/********************************************************************
    created:    2008/08/10
    filename:     timermanager.cpp
    author:        Lichuang
                
    purpose:    定時器管理器
********************************************************************
*/

#include 
"timermanager.h"
#include 
<sys/time.h>

static void Process(int nSigNo);

CTimerManager::CTimerManager()
    : m_nInterval(
0)
    , m_nIdCount(
0)      
{
}

CTimerManager::
~CTimerManager()
{
}

int CTimerManager::AddTimer(TTimeEvent& tTimeEvent)
{
    list
<TTimeEvent>::iterator Iter1 = m_lEvent.begin();
    
return AddTimer(Iter1, tTimeEvent, true);
}

int CTimerManager::DelTimer(int nId)
{
    list
<TTimeEvent>::iterator Iter1 = m_lEvent.begin(), Iter2 = m_lEvent.end();
    
for (; Iter1 != Iter2; ++Iter1)
    {
        
if (Iter1->nId == nId)
        {
            
break;
        }
    }
    
if (Iter1 == Iter2)
    {
        
return -1;
    }

    
int nSecondsLeft = Iter1->nSecondsLeft;
    Iter2 
= Iter1;
    
++Iter2;
    m_lEvent.erase(Iter1);
    
// 刪除一個定時器還要更新下一個節(jié)點(如果存在的話)的相對時間
    if (m_lEvent.end() != Iter2)
    {
        Iter2
->nSecondsLeft += nSecondsLeft;
    }

    
return 0;
}

void CTimerManager::PrintTimerList()
{
    list
<TTimeEvent>::iterator Iter1 = m_lEvent.begin(), Iter2 = m_lEvent.end();
    
for (; Iter1 != Iter2; ++Iter1)
    {
        printf(
"id = %d, interval = %d, secondleft = %d\n", Iter1->nId, Iter1->nInterval, Iter1->nSecondsLeft);
    }
}

int CTimerManager::Start()
{
    
return SetTimer(::Process);
}

int CTimerManager::Stop()
{
    m_nInterval 
= 0;
    
return SetTimer(SIG_DFL);
}

int CTimerManager::Init(int nInterval)
{
    m_nInterval 
= nInterval;

    
return 0;
}

int CTimerManager::SetTimer(sighandler_t pFn)
{
    
struct itimerval interval;
        
    interval.it_interval.tv_sec 
= m_nInterval;
    interval.it_interval.tv_usec 
= 0;
    interval.it_value.tv_sec 
= m_nInterval;
    interval.it_value.tv_usec 
= 0;

    
if (0 != ::setitimer(ITIMER_REAL, &interval, NULL)) 
    {
        
return -1;
    }    

    
if (0 != ::signal(SIGALRM, pFn))
    {
        
return -1;
    }

    
return 0;
}

int CTimerManager::AddTimer(list<TTimeEvent>::iterator& tPos, TTimeEvent& tTimeEvent, bool bIsNewEvent)
{
    
// 根據(jù)觸發(fā)時間的升序排列, 將定時器放在鏈表的合適位置
    list<TTimeEvent>::iterator Iter1 = tPos, Iter2 = m_lEvent.end();
    
int nSecondsLeft = 0;
    
for (; Iter1 != Iter2; nSecondsLeft += Iter1->nSecondsLeft, ++Iter1)
    {
        
if (Iter1->nSecondsLeft + nSecondsLeft > tTimeEvent.nInterval)
        {
            
break;
        }
    }

    tTimeEvent.nSecondsLeft 
= tTimeEvent.nInterval - nSecondsLeft;
    
// 如果插入節(jié)點不是定時器鏈表的最后一個節(jié)點, 那么要修改它下一個節(jié)點的相對時間值
    if (Iter1 != Iter2)
    {
        Iter1
->nSecondsLeft = Iter1->nSecondsLeft - tTimeEvent.nSecondsLeft;
    }
    
if (bIsNewEvent)
    {
        tTimeEvent.nId 
= m_nIdCount++;
    }

    m_lEvent.insert(Iter1, tTimeEvent);

    
return tTimeEvent.nId;
}

int CTimerManager::Process()
{
    
// 如果定時器鏈表是空的, 立即返回
    if (m_lEvent.empty())
    {
        
return 0;
    }

    
// 如果定時器鏈表的頭結(jié)點沒有到該觸發(fā)的時間, 更新已經(jīng)過去的時間計數(shù)器后返回
    list<TTimeEvent>::iterator Iter1 = m_lEvent.begin();
    Iter1
->nSecondsLeft -= m_nInterval;
    
if (0 < Iter1->nSecondsLeft)
    {
        
return 0;
    }

    
// 定時器鏈表的頭結(jié)點已經(jīng)可以觸發(fā), 從頭結(jié)點開始遍歷鏈表, 看看哪些結(jié)點也可以觸發(fā)事件的
    list<TTimeEvent>::iterator Iter2 = m_lEvent.end();
    list
<TTimeEvent> lEvent;
    
while (Iter1 != Iter2)
    {
        
if (0 >= Iter1->nSecondsLeft)
        {
            
// 觸發(fā)定時事件
            Iter1->pFn(Iter1->pArg);
            
if (TIMER_CIRCLE == Iter1->nType)
            {
                lEvent.push_back(
*Iter1);
            }
            
++Iter1;
            m_lEvent.pop_front();
        }
        
else
        {
            
break;
        }
    }

    
// 將本次觸發(fā)的定時器事件重新插入到定時器鏈表中
    
// 這里有一個優(yōu)化策略: nLastInterval 保存上一個重新插入到定時器鏈表中的時間間隔
    
// 如果這個值比當前節(jié)點的時間間隔小, 那么從上一個插入的位置開始搜索
    
// 否則從定時器節(jié)點的開始位置搜索
    int nLastInterval = 0;
    list
<TTimeEvent>::iterator Iter3;
    
for (Iter1 = lEvent.begin(), Iter2 = lEvent.end(); Iter1 != Iter2; nLastInterval = Iter1->nInterval, ++Iter1)
    {
        
if (0 == nLastInterval || nLastInterval > Iter1->nInterval)
        {
            Iter3 
= m_lEvent.begin();
        }

        AddTimer(Iter3, 
*Iter1, false);
    }

    
return 0;
}

void Process(int nSigNo)
{
    
if (nSigNo == SIGALRM)
    {
        CTimerManager::GetInstance()
->Process();
    }
}



posted on 2008-08-13 15:36 那誰 閱讀(2952) 評論(2)  編輯 收藏 引用 所屬分類: 服務(wù)器設(shè)計Linux/Unix

評論

# re: 服務(wù)器公共庫開發(fā)--定時器管理器模塊  回復(fù)  更多評論   

比較猥瑣.. 你參考一下ACE吧. perfect

你要做服務(wù)器編程.不可能總是避諱多線程環(huán)境. 嘗試一下select吧.
2008-08-14 09:43 | bugs_killer

# re: 服務(wù)器公共庫開發(fā)--定時器管理器模塊[未登錄]  回復(fù)  更多評論   

@bugs_killer
select我當然有用,只是不用多線程罷了.我寫的服務(wù)器都是多進程+多路復(fù)用IO的模式.

2008-08-14 10:21 | 創(chuàng)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品久久久蜜桃| 欧美激情一区二区三区蜜桃视频| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ入口 | 亚洲第一黄色网| 久久综合九色99| 老司机免费视频一区二区三区| 亚洲视频999| 国产一区二区三区高清播放| 久久午夜国产精品| 99精品国产热久久91蜜凸| 欧美成人一区二区| 久久狠狠婷婷| 欧美激情按摩在线| 久久亚洲图片| 欧美视频一区二区在线观看| 久久久久久亚洲精品中文字幕| 免费高清在线视频一区·| 亚洲视频免费在线| 欧美大成色www永久网站婷| 亚久久调教视频| 欧美日韩四区| 亚洲美女视频在线观看| 91久久久久久国产精品| 久久久国产一区二区三区| 午夜伦理片一区| 国产精品欧美日韩一区二区| 亚洲免费播放| 亚洲校园激情| 国产精品极品美女粉嫩高清在线 | 午夜精品国产更新| 欧美日韩亚洲在线| 中文精品视频| 久久久久se| 亚洲激情小视频| 欧美日韩性生活视频| 99国产精品国产精品毛片| 亚洲一区二区三区视频| 国产精品免费区二区三区观看| 亚洲欧美成人在线| 欧美精品在线观看91| 亚洲品质自拍| 亚洲欧美日本视频在线观看| 国产精品美女主播| 久久躁日日躁aaaaxxxx| 亚洲精品小视频在线观看| 亚洲欧美国产高清va在线播| 一区二区三区无毛| 欧美精品日韩综合在线| 久久av一区二区| 一本一本久久a久久精品牛牛影视| 性娇小13――14欧美| 亚洲精品国产视频| 激情久久久久久久| 欧美调教vk| 欧美日韩亚洲一区二| 久久青草欧美一区二区三区| 日韩一级黄色片| 亚洲激情六月丁香| 欧美风情在线| 欧美激情视频在线播放| 狂野欧美激情性xxxx欧美| 西西人体一区二区| 亚洲性感美女99在线| 夜夜嗨一区二区三区| 亚洲人屁股眼子交8| 亚洲精品九九| 亚洲精品一区二| 99精品视频免费观看视频| 亚洲人体影院| 亚洲视频一二三| 亚洲综合精品一区二区| 亚洲午夜视频在线观看| 亚洲一区二区在线视频| 欧美中文字幕精品| 美女诱惑黄网站一区| 亚洲二区三区四区| 亚洲特级毛片| 免费国产一区二区| 国产精品日韩久久久| 欧美午夜不卡影院在线观看完整版免费| 久久精品一本| 欧美激情亚洲一区| 国产欧美精品国产国产专区| 狠狠综合久久av一区二区老牛| 在线精品在线| 羞羞色国产精品| 亚洲高清不卡在线| 欧美一级视频免费在线观看| 母乳一区在线观看| 国内外成人免费激情在线视频| 亚洲人成人一区二区三区| 欧美在线一二三区| 亚洲精品国产品国语在线app| 欧美亚洲视频一区二区| 欧美日韩一区二区视频在线观看 | 欧美在线视频在线播放完整版免费观看| 欧美一区二区在线观看| 国产精品豆花视频| 中日韩男男gay无套| 亚洲人成网站在线观看播放| 久久久噜噜噜久久狠狠50岁| 国产精品社区| 欧美一级夜夜爽| 午夜精品在线观看| 国产精品自拍网站| 久久国产综合精品| 久久久久久久久久久一区| 国产精品一区二区在线观看网站 | 午夜宅男欧美| 一本色道久久综合| 美女图片一区二区| 日韩视频专区| 亚洲色图自拍| 影音先锋久久| 日韩亚洲视频在线| 国产欧美欧洲在线观看| 欧美日韩免费一区二区三区| 亚洲一区二区成人在线观看| 香蕉精品999视频一区二区| 国产女人aaa级久久久级| 美女久久网站| 国产乱码精品| 亚洲国产你懂的| 国产精品亚洲一区| 亚洲国产成人精品久久久国产成人一区| 美女亚洲精品| 久久激情综合网| 欧美日韩爆操| 91久久精品国产91久久性色| 国产日韩欧美精品在线| 99在线精品视频| 亚洲欧美一区二区三区在线 | 亚洲一区二区三区精品动漫| 亚洲精品日本| 国产精品久久久久婷婷| 久久久久久亚洲精品不卡4k岛国| 免费h精品视频在线播放| 亚洲午夜精品久久久久久app| 欧美成人精品| 免费看精品久久片| 亚洲专区免费| 老色批av在线精品| 日韩午夜电影在线观看| 亚洲一区观看| 亚洲一区在线观看免费观看电影高清| 久久av二区| 免费成人网www| 国内成人精品一区| 久久国产黑丝| 牛夜精品久久久久久久99黑人 | 亚洲一区二区三区涩| 一区二区三区久久精品| 欧美极品一区二区三区| 91久久视频| 99精品免费网| 国产女优一区| 亚洲性av在线| 久久精品91久久久久久再现| 国产亚洲激情视频在线| 久久久久久久综合色一本| 欧美第一黄色网| 欧美激情按摩在线| 亚洲色图制服丝袜| 国产精品免费在线| 久久精品视频在线看| 欧美xart系列高清| 亚洲视频在线二区| 在线不卡欧美| 国产精品青草久久| 久久婷婷综合激情| 在线综合亚洲欧美在线视频| 久久午夜电影| 亚洲欧美视频一区| 亚洲激情啪啪| 一区二区三区在线视频播放| 国产精品视频一区二区三区| 美乳少妇欧美精品| 久久精品国产一区二区三| 一区二区三区色| 亚洲另类自拍| 久久亚洲电影| 久久免费99精品久久久久久| 亚洲一区日本| 亚洲欧美日产图| 午夜精品短视频| 亚洲一区www| 欧美夜福利tv在线| 亚洲欧美日韩系列| 亚洲综合色激情五月| 亚洲性感激情| 午夜精品国产精品大乳美女| 亚洲一区二区三区影院| 亚洲在线播放| 久久国产婷婷国产香蕉| 欧美资源在线| 欧美国产先锋| 亚洲欧美怡红院| 免费亚洲电影在线观看| 欧美大尺度在线观看| 欧美日韩国产电影|