国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

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

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

一:分析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 #define ebitsize ( 1 #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)定時器管理類  

定時器管理類  

1/**////  

2/// 定時器管理類,管理定時器的五個輪子  

3///  

4class CTimer  

5{  

6public:  

7 /**////  

8 /// 構造函數如下  

9 ///  

10 CTimer(void);  

11  

12 CTimer( int second);  

13  

14 "CTimer(void);  

15  

16public:  

17 /**////  

18 /// 初始化定時器管理類  

19 ///  

20 void Init(int Second = 0);  

21  

22 /**////  

23 /// 增加一個定時器  

24 ///  

25 void add_timer(timernode *times );  

26  

27 /**////  

28 /// 檢測定時器是否存在  

29 ///  

30 /// @return 如果存在返回true,否則為false  

31 ///  

32 bool check_timer(timernode* times);  

33  

34 /**////  

35 /// 刪除定時器  

36 ///  

37 /// @return 如果刪除成功返回true,否則為false  

38 ///  

39 bool delete_timer(CLinkList* list, timernode *times);  

40  

41 /**////  

42 /// 重新初始化一個定時器  

43 ///  

44 void init_timer(timernode* timers);  

45  

46 /**////  

47 /// 定時器的遷移,也即將一個定時器從它原來所處的定時器向量遷移到另一個定時器向量中。  

48 ///  

49 void cascade_timer(CLinkList* timers);  

50  

51 /**////  

52 /// 執行當前已經到期的定時器,所有小于jeffies的定時器  

53 ///  

54 void Expires( ulong jeffies);  

55  

56 /**////  

57 /// 重新初始化一個定時器  

58 ///  

59 void Cancel(timernode* timers);  

60  

61 /**////  

62 /// 重新計算一個定時器  

63 ///  

64 void Mod_timer(timernode* timers);  

65  

66private:  

67 /**//// 5個輪子  

68 CLinkList* m_tv1;  

69 CLinkList* m_tv2;  

70 CLinkList* m_tv3;  

71 CLinkList* m_tv4;  

72 CLinkList* m_tv5;  

73 CLinkList** g_vecs;  

74  

75 /**//// 定時器全局tick  

76 ulong m_jeffies;  

77 /**//// 上次運行時間  

78 ulong m_Lasttime;  

79 /**//// 精確到毫秒  

80 ulong m_mSecond;  

81};  

82  

四: 測試  

通過本文的介紹可以理解次定時器的的查找,刪除,插入都是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 15 break;  

16 case eTimer2:  

17 std::cout 18 break;  

19 case eTimer3:  

20 std::cout 21 break;  

22 default:  

23 std::cout 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 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 58 59 60 61 return 0;  

62}
本文地址:http://www.qingdxww.cn/thread-22415-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • Dev Tool Bits——使用MPLAB® Discover瀏覽資源
  • Dev Tool Bits——使用條件軟件斷點宏來節省時間和空間
  • Dev Tool Bits——使用DVRT協議查看項目中的數據
  • Dev Tool Bits——使用MPLAB® Data Visualizer進行功率監視
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 免费久久久久 | 在线视频三区 | 精品久久中文久久久 | 国产亚洲婷婷香蕉久久精品 | 国产精品女 | 67194精品| 色一情一伦一区二区三 | a在线观看免费网址大全 | 欧美在线视频免费播放 | 日韩天堂在线 | 青青青手机在线视频 | 国产精品一区在线播放 | 日日噜噜夜夜狠狠tv视频免费 | 俄罗斯丰满护士乱 | 国产成人高清亚洲一区久久 | 91免费精品国自产拍在线可以看 | 全国男人天堂网 | 在线高清国产 | 成人国产三级在线播放 | 色视频在线免费观看 | 精品欧美一区视频在线观看 | 亚洲综合极品香蕉久久网 | 日韩高清在线不卡 | 中文字幕日韩一区二区不卡 | 国产精品极品 | 久久久久国产 | 亚洲精品国产精品乱码不97 | 成人深爱网 | 91av官网| 天堂网在线观看在线观看精品 | 农村寡妇一级毛片免费播放 | 天天噜 | 91国在线国内在线播放 | 日本aaa视频 | 色版网站| 毛片在线播放视频 | 日韩精品一区二区在线观看 | 九九热九九 | 国产91中文剧情在线观看 | 精品视频网 | 欧美日韩黑人 |