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

勤能補拙,Expter

成都游戲Coder,記錄游戲開發過程的筆記和心得!

一個高效的定時器分析及設計

       對于一個游戲而言,定時器是必須的,而它一般作為一個游戲基本公共組件,而定時器在游戲邏輯中運用是非常明顯的(比如吃藥回血,每幾秒回血多少),而對于游戲邏輯而言需要開發一個高效率高精度(毫秒級別)的定時器。

    
一:分析Ace庫定時器實現方式

   1.Ace種定時器實現有4種,這里不具體介紹實現細節,主要介紹實現數據結構,性能。
       具體的4種定時器都是從ACE_Timer_Queue_T繼承,每種定時器用不同的數據結構來實現具體Timer的算法。
      1)ACE_Timer_Heap定時器,根據觸發時間建立一個優先級隊列(一個最小堆數據結構)來維護所有的定時器,代價就是刪除和插入過程為O(logn),代價比較高。
      2)ACE_Timer_List定時器,根據觸發時間建立一個有序的雙向鏈表,代價就是插入定時器代價較高。
      3)ACE_Timer_Hash定時器,采用開鏈的Hash方式每一個桶為一個單鏈表,在檢查所有桶超時的時候會遍歷鏈表所有的元素。為了提高效率這里所用的Hash桶應該足夠 大,而對于定時器一般是頻繁的超時響應定時器,已經插入和刪除,響應會采用迭代的方式。所以效率并不是那么高效。
      4)ACE_Timer_Wheel定時器,采用的一種時間輪的方式,具體實現就好象一個輪子上面有很多插槽,每一個插槽下面包括一個有序雙向鏈表,在Ace中把輪子叫做Wheel,插槽叫做Spoke,每一個定時器被Hash到Spoke中,而Spoke也可以理解為timer的分辨率,而Spoke的計算公式為 :( 觸發時間 >> 分辨率的位數)&(spoke大小-1).然后在根據觸發時間把定時器插入到每一個Spoke的有序雙向鏈表中, 與Ace_timer_Hash的實現類似,只是這里用戶可以指定Spoke大小。這里代價就是插入的時候可能最壞為O(n).
    
      我們公司現在CTimer就是采用Ace的ACE_Timer_Wheel原理設計的
      這里有一個圖更能直觀的描述這種思想:
    
           實現方式為Vector,list組合。


 二: 本文介紹一種采用linux中斷處理的定時器設計方式  
     此定時器的查找,刪除,插入都是O(1)
     1) 介紹設計原理
     定時器是基于時間的中斷函數,即是根據觸發時間來超時響應。所以只要我們設計一個基于時間的Hash算法。只要我們能我們把一個函數觸發時間全部Hash到此Hash算法的桶中,就實現了查找,插入,刪除O(1)的操作了,其實不然基于時間的hash算法好像挺復雜,而且桶的數量太大,內存消耗太多,所以把一個時間直接Hash代價太大。是否有一種其他的方式呢,linux中斷處理采用一種類似水表計算水量的方式,方式就是生活中的水表,第一個指針轉一圈后一個轉一格,假設每一個圈都是10個刻度,第一個圈能表示10,那么第二圈沒一個刻度表示第一個圈的1圈,就能表示10*10, 二個圈一共就能表示10*10 + 10。 以此類推,5個圈就能表示10^5+10^4+10^3+10^2+10...

      一個32bits的整數,如果精確到1毫秒,則2^32位可以表示49.3天,而一般服務器應該不會直接運行49.3天,這里我們采用5個輪子(即圈), 輪子大小分別為256,64,64,64,64 ,輪子依次類推表示范圍在0~256, 256~256*64, 256*64~256*64^2, 256*64^2~256*64^3, 256*64^3~256*64^4, 假設這里精度為n毫秒,第一個輪子表示n*256秒時間內觸發函數,第二個輪子的第二個插孔則表示n*256*2時間范圍內的,

    2)一些定義:
           A. 輪子,這里采用的輪子與上面介紹的Ace輪子大概一樣,一個循環列隊,每一個插槽你們有一個雙向鏈表,注意這里鏈表不需要排序,所以在插入的是O(1)的操作。輪子為5個。

    3)  操作:
           A. Hash算法:這里Hash算法根據他的多少時間后觸發,直接Hash得到輪子以及插槽,然后插入到某個插槽雙向的鏈表中。
           B.定時器觸發: 定時器觸發只會觸發第一個輪子超時的所有定時器,因為后面4個輪子定時器表示都在前1輪子觸發完了才會觸發,所以這里讓后面4個輪子維護表示將要發生的定時。這里會根據當第一個輪子轉第幾圈后,第二個輪子會把第幾插槽的所有定時器全部插入到第一個輪子中,依次類推,第二個輪子轉一個第三個輪子某個插槽又會插入到第二個輪子中。。。
           
   4)注意的地方:
          A.將一個定時器插入到它應該所處的定時器輪子插槽中。
          B.定時器的遷移,也即將一個定時器從它原來所處的輪子插槽遷移到另一個輪子插槽中。
          C.超時響應執行當前已經到期的定時器。

三:編碼實現
         1) 常量定義
                   
/// define m
#define lnum        5
#define sbits        6
#define ebits        8
#define sbitsize    ( 1 << sbits )
#define ebitsize    ( 1 << ebits )
#define sMask        ( sbitsize- 1)
#define eMask        ( ebitsize -1)

         2) 數據結構
                 
 1/// 定時器指針結點
 2struct ListNode
 3{
 4    ListNode *next,*prev;
 5}
;
 6
 7///
 8/// 定時器類型
 9/// 

10enum eTimerType
11{
12    eTimer1 = 10,
13    eTimer2 ,
14    eTimer3 
15}
;
16
17/// 
18/// 定時器結點,tlist表示結點的指針,expires循環周期時間
19/// etime 觸發周期時間,pFun觸發函數.
20/// 

21struct timernode
22{
23    ListNode    tlist;
24    ulong       expires;
25    ulong       etime;
26    void        *pFun;
27    eTimerType  eType;
28}
;
  3) 輪子類
                     
 1///              
 2/// 一個輪子,一個循環隊列
 3/// 
 4/// 

 5class CLinkList
 6{
 7
 8public:
 9
10    CLinkList(void);
11
12    CLinkList( int size );
13    
14    ~CLinkList(void);
15    
16    /// 
17    /// 初始化
18    /// 

19    void  init();
20
21    /// 
22    /// 讓指針指向自己
23    /// 

24    void  init_list_self( int  index);
25
26    /// 
27    /// 把news插入到prev,next之間
28    /// 

29    void  insert_listnode(ListNode *news , ListNode* prev , ListNode* next);
30
31    /// 
32    /// 插入到鏈表頭
33    /// 

34    void  insert_head( ListNode* news , ListNode* head );
35
36    ///
37    /// 插入到鏈表尾
38    /// 

39    void  insert_tail( ListNode* news , ListNode* head );
40
41    /// 
42    /// 刪除節點
43    /// 

44    void  list_del( ListNode* list);
45
46    /// 
47    /// 得到改輪子轉到第幾個插槽
48    ///

49    int        GetIndex( ) const return m_index ;}
50
51    ///
52    /// 更新輪子的插槽
53    ///

54    void       SetIndex(int idx) { m_index = idx  ;}
55
56    /// 
57    /// 得到輪子插槽的指針 
58    ///

59    ListNode*  GetNode(int index) const;
60
61private:
62    ///
63    /// 輪子的插槽數組
64    /// 

65    ListNode *m_List;  
66    
67    ///
68    /// 輪子當前轉到的索引
69    /// 

70    int          m_index; 
71
72    ///
73    /// 輪子大小
74    ///

75    int       m_Size;
76
77}
;

         4)定時器管理類
                
定時器管理類


四: 測試
         通過本文的介紹可以理解次定時器的的查找,刪除,插入都是O(1)的復雜度。

  
/// 游戲事件基類
class   CGameEvent
{
public:
    
virtual  long  TimeOut( eTimerType type) = 0;
}
;

測試例子:
 1long  Sum1= 0 ;
 2long  Sum2= 0 ;
 3long  Sum3= 0 ;
 4long  Sum = 0;
 5
 6class  CTimerTest : public   CGameEvent
 7{
 8public:
 9    long TimeOut( eTimerType type)
10    {
11        switch ( type)
12        {
13        case eTimer1:
14            std::cout <<"Sum1 = "<< Sum1 ++ << std::endl;
15            break;
16        case eTimer2:
17            std::cout <<"Sum2 = "<< Sum2 ++ << std::endl;
18            break;
19        case eTimer3:
20            std::cout <<"Sum3 = "<< Sum3 ++ << std::endl;
21            break;
22        default:
23            std::cout <<"Sum  = "<< Sum ++ << std::endl;
24            break;
25        }

26        return 0;
27    }

28}
;
29
30int _tmain(int argc, _TCHAR* argv[])
31{
32    CTimer  mytimer( 40 );
33    
34    long    n;
35    std::cin >> n;
36    CTimerTest test;
37    for ( int i = 0 ; i < n ; i++ )
38    {
39        timernode* tim = new timernode ;
40        tim->expires  = 0;
41        tim->etime    = GetCurrSystemTime() + (rand() % 1000 ) * 6;
42        tim->pFun     =&test;
43        tim->eType    =(eTimerType)( i%3 + 10 );
44
45        mytimer.add_timer( tim );
46    }

47
48    for ( ;; )
49    {
50        if ( (Sum1 + Sum2 + Sum3) == n )
51            break;
52
53        /// 運行所有的定時器
54        mytimer.Expires( GetCurrSystemTime() );
55    }

56
57    std::cout << " sum1 = " << Sum1 
58              << " sum2 = " << Sum2 
59              << " sum3 = " << Sum3 
60              << " sum  = " << Sum ;
61    return 0;
62}

63

上面的具體代碼:http://code.google.com/p/tpgame/source/browse/#svn/trunk/CTimer/CTimer


最近2篇學習筆記將介紹:
1.參考多種內存管理模型的自己寫的內存管理模塊。
2.最近學習的Ai算法總匯。

posted on 2010-03-05 16:28 expter 閱讀(9163) 評論(12)  編輯 收藏 引用 所屬分類: 工作筆記算法與數據結構

評論

# re: 一種高效的定時器設計 2010-03-05 21:42 expter

整了半天,格式有點問題,現在看了下還是有點問題。。  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-07 22:59 何清龍

沒關系。
因為有問題,才會需要C++程序員。哈哈  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-07 23:08 hr

我們公司有游戲職位,是否有興趣。
已經聯系你了:)  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-08 10:01 何清龍

想過了,我技術還不夠,時間也不充裕。謝謝好意。  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-08 16:00 expter

@何清龍
你在說什么哦。。。  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-23 18:33 guest

>>這里會根據當第一個輪子轉第幾圈后,第二個輪子會把第幾插槽的所有定時器全部插入到第一個輪子中

有個疑問。。假設第二個輪子的第幾插槽上的定時器有100個,要對這100個定時器全部hash一遍,才插入到第一個輪子對應的插槽吧?

這樣貌似的消耗還是有點大  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-23 22:17 expter

@guest
不會的,而且定時器的代價主要在遍歷響應超時定時器結點。
而且插入式線性的,我做過測試對于100W個定時器插入時間不到1S。。。  回復  更多評論   

# re: 一個高效的定時器分析及設計 2010-03-24 00:00 guest

@expter
想了一下,第2輪子要等第一個輪子轉動一圈之后才會轉動一次,總體來說還是接近O(1)。。。

借鑒樓主的思路了:)  回復  更多評論   

# re: 一個高效的定時器分析及設計 2012-04-01 16:51 醬油男

就像鐘表的時分秒針一樣會遇到0點問題,三針重合會遍歷處理所有鏈表。  回復  更多評論   

# re: 一個高效的定時器分析及設計 2013-07-24 08:33 =XTK

很好的設計,如果我想中途中止這個定時器,那還沒有這個接口..不過我準備自己加上,準備用人你的這份設計啦..很好很強大..  回復  更多評論   

# re: 一個高效的定時器分析及設計 2014-01-03 16:38 simaocat

你好,請問主函數中CTimer mytimer( 40 );這個40代表什么意思呢,為什么算expires時間的時候要除以這個40, 其單位是秒還是毫秒  回復  更多評論   

# re: 一個高效的定時器分析及設計 2015-05-28 20:16 aaa

http://code.google.com/p/tpgame/source/browse/#svn/trunk/CTimer/CTimer
這個網址打不開啊!  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧洲在线一区| 欧美一区国产在线| 欧美激情一区二区三区高清视频| 久久精品视频免费播放| 黑人巨大精品欧美一区二区 | 欧美综合激情网| 国内精品久久久久久久果冻传媒| 久久伊人一区二区| 欧美精品二区三区四区免费看视频| 亚洲精品一区二区网址| 99精品99| 国产农村妇女精品一二区| 亚洲欧美日韩一区二区在线| 亚洲在线网站| 国产一区二区黄色| 亚洲高清在线精品| 欧美色道久久88综合亚洲精品| 亚洲一区在线免费观看| 欧美自拍偷拍午夜视频| 亚洲免费久久| 一区二区三区日韩精品视频| 国产亚洲福利社区一区| 欧美福利一区二区三区| 欧美夫妇交换俱乐部在线观看| 欧美成人精品不卡视频在线观看| 亚洲综合首页| 久久精品国产第一区二区三区最新章节 | 一区二区三区视频观看| 久久综合久久久| 日韩视频在线永久播放| 亚洲一区二区久久| 在线播放豆国产99亚洲| 亚洲精品视频一区| 国内精品久久久久影院色| 亚洲黄一区二区三区| 国产热re99久久6国产精品| 欧美成va人片在线观看| 国产伦精品一区二区| 亚洲第一在线综合网站| 国产欧美在线观看一区| 亚洲精品久久久久| 亚洲国产精品精华液网站| 中文亚洲视频在线| 一区二区精品在线观看| 免费亚洲一区| 久久综合电影| 国产欧美韩国高清| 亚洲午夜久久久久久久久电影网| 亚洲精品韩国| 免费欧美日韩| 欧美大片va欧美在线播放| 国产一区二区三区在线观看免费 | 亚洲欧美国产精品va在线观看| 欧美韩国日本综合| 免费看的黄色欧美网站| 国产亚洲一级高清| 性欧美精品高清| 久久精品国产77777蜜臀| 国产精品免费网站在线观看| 一区二区三区四区国产精品| 亚洲色图制服丝袜| 欧美日韩国产精品一区二区亚洲 | 在线视频亚洲一区| 牛人盗摄一区二区三区视频| 蜜臀久久久99精品久久久久久| 国产午夜亚洲精品理论片色戒| 亚洲综合成人在线| 久久国产黑丝| 狠狠色丁香久久综合频道| 久久狠狠一本精品综合网| 久久中文字幕一区| 最新精品在线| 欧美日韩精品免费在线观看视频| 亚洲精品你懂的| 91久久精品国产91久久性色| 美国三级日本三级久久99| 亚洲国产人成综合网站| 亚洲宅男天堂在线观看无病毒| 国产美女精品一区二区三区| 亚洲欧美日韩系列| 久久香蕉国产线看观看av| 怡红院精品视频| 欧美国产视频在线| 亚洲日本一区二区三区| 亚洲综合电影| 韩国av一区二区三区| 久久一区二区三区av| 欧美电影资源| 亚洲一区尤物| 国产一区二区福利| 欧美黄色影院| 午夜在线a亚洲v天堂网2018| 欧美 亚欧 日韩视频在线| 一二三区精品福利视频| 国产精品区二区三区日本 | 女女同性精品视频| 亚洲黄色影片| 国产精品午夜电影| 久久―日本道色综合久久| 99成人在线| 久久综合一区二区三区| 亚洲精品韩国| 国产专区精品视频| 欧美另类69精品久久久久9999| 久久精品观看| 99re8这里有精品热视频免费| 国产精品一区在线观看| 女同性一区二区三区人了人一 | 久久成年人视频| 亚洲免费观看高清完整版在线观看| 国产精品―色哟哟| 欧美精品一区二区高清在线观看| 午夜免费日韩视频| 99视频有精品| 亚洲福利专区| 久久人人97超碰国产公开结果| 一区二区高清在线| 亚洲第一伊人| 国语自产精品视频在线看一大j8 | 亚洲一区三区电影在线观看| 久久亚洲春色中文字幕久久久| 一区二区三区高清| 亚洲黄色免费电影| 在线播放日韩专区| 国产欧美在线看| 国产精品视频网址| 欧美日韩一区二区国产| 欧美激情综合| 免费国产一区二区| 久久久久久免费| 欧美在线网站| 欧美一区二区性| 午夜精品久久久久久久久久久久| 夜夜躁日日躁狠狠久久88av| 亚洲黄色成人久久久| 欧美电影免费观看大全| 美女免费视频一区| 老牛嫩草一区二区三区日本| 久久av一区二区三区| 欧美一级黄色录像| 欧美一区激情| 久久久久国产精品一区| 久久色中文字幕| 久热精品视频在线免费观看| 久久在线精品| 欧美韩日一区二区| 亚洲高清毛片| 最新精品在线| 中日韩美女免费视频网站在线观看| 亚洲精品欧美在线| 欧美一级精品大片| 久久久精品国产一区二区三区| 久久激情五月丁香伊人| 久久久久欧美精品| 欧美成人午夜| 亚洲精品国产品国语在线app | 性久久久久久久久| 欧美综合国产精品久久丁香| 久久一区二区精品| 欧美福利视频在线观看| 最新日韩精品| 午夜精品久久久久久99热| 久久久久久久尹人综合网亚洲| 蜜桃av一区二区三区| 欧美伦理在线观看| 国产精品女主播| 影音先锋中文字幕一区二区| 亚洲伦伦在线| 欧美在线1区| 欧美国产第二页| 一本久道久久久| 久久爱91午夜羞羞| 欧美成人午夜激情| 国产精品实拍| 亚洲精品视频免费| 欧美一区二视频在线免费观看| 蜜桃av一区二区在线观看| 亚洲九九九在线观看| 午夜精品一区二区三区四区 | 亚洲久久成人| 久久亚洲综合网| 欧美午夜视频在线| 亚洲第一在线| 欧美一级理论片| 亚洲第一精品影视| 午夜久久一区| 欧美午夜精品久久久久久超碰| 伊人婷婷欧美激情| 午夜精品久久久久| 亚洲高清毛片| 久久都是精品| 国产欧美日韩综合一区在线观看 | 欧美日韩的一区二区| 国产精品免费视频xxxx| 亚洲美女av网站| 久久野战av| 午夜精品久久久久久久99樱桃| 欧美久久99| 亚洲全部视频| 欧美高清不卡在线|