llkeyusetracker.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:5k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llkeyusetracker.h
  3.  * @brief Declaration of the LLKeyUseTracker class.
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #ifndef LL_KEYUSETRACKER_H
  33. #define LL_KEYUSETRACKER_H
  34. // This is a generic cache for an arbitrary data type indexed against an
  35. // arbitrary key type. The cache length is determined by expiration time
  36. // tince against last use and set size. The age of elements and the size
  37. // of the cache are queryable.
  38. //
  39. // This is implemented as a list, which makes search O(n). If you reuse this
  40. // for something with a large dataset, consider reimplementing with a Boost
  41. // multimap based on both a map(key) and priority queue(last_use).
  42. template <class TKey, class TData>
  43. class KeyUseTrackerNodeImpl
  44. {
  45. public:
  46. U64 mLastUse;
  47. U32 mUseCount;
  48. TKey mKey;
  49. TData mData;
  50. KeyUseTrackerNodeImpl( TKey k, TData d ) :
  51. mLastUse(0),
  52. mUseCount(0),
  53. mKey( k ),
  54. mData( d )
  55. {
  56. }
  57. };
  58. template <class TKey, class TData>
  59. class LLKeyUseTracker
  60. {
  61. typedef KeyUseTrackerNodeImpl<TKey,TData> TKeyUseTrackerNode;
  62. typedef std::list<TKeyUseTrackerNode *> TKeyList;
  63. TKeyList mKeyList;
  64. U64 mMemUsecs;
  65. U64 mLastExpire;
  66. U32 mMaxCount;
  67. U32 mCount;
  68. static U64 getTime()
  69. {
  70. // This function operates on a frame basis, not instantaneous.
  71. // We can rely on its output for determining first use in a
  72. // frame.
  73. return LLFrameTimer::getTotalTime();
  74. }
  75. void ageKeys()
  76. {
  77. U64 now = getTime();
  78. if( now == mLastExpire )
  79. {
  80. return;
  81. }
  82. mLastExpire = now;
  83. while( !mKeyList.empty() && (now - mKeyList.front()->mLastUse > mMemUsecs ) )
  84. {
  85. delete mKeyList.front();
  86. mKeyList.pop_front();
  87. mCount--;
  88. }
  89. }
  90. TKeyUseTrackerNode *findNode( TKey key )
  91. {
  92. ageKeys();
  93. typename TKeyList::iterator i;
  94. for( i = mKeyList.begin(); i != mKeyList.end(); i++ )
  95. {
  96. if( (*i)->mKey == key )
  97. return *i;
  98. }
  99. return NULL;
  100. }
  101. TKeyUseTrackerNode *removeNode( TKey key )
  102. {
  103. TKeyUseTrackerNode *i;
  104. i = findNode( key );
  105. if( i )
  106. {
  107. mKeyList.remove( i );
  108. mCount--;
  109. return i;
  110. }
  111. return NULL;
  112. }
  113. public:
  114. LLKeyUseTracker( U32 memory_seconds, U32 max_count ) :
  115. mLastExpire(0),
  116. mMaxCount( max_count ),
  117. mCount(0)
  118. {
  119. mMemUsecs = ((U64)memory_seconds) * 1000000;
  120. }
  121. ~LLKeyUseTracker()
  122. {
  123. // Flush list
  124. while( !mKeyList.empty() )
  125. {
  126. delete mKeyList.front();
  127. mKeyList.pop_front();
  128. mCount--;
  129. }
  130. }
  131. void markUse( TKey key, TData data )
  132. {
  133. TKeyUseTrackerNode *node = removeNode( key );
  134. if( !node )
  135. {
  136. node = new TKeyUseTrackerNode(key, data);
  137. }
  138. else
  139. {
  140. // Update data
  141. node->mData = data;
  142. }
  143. node->mLastUse = getTime();
  144. node->mUseCount++;
  145. mKeyList.push_back( node );
  146. mCount++;
  147. // Too many items? Drop head
  148. if( mCount > mMaxCount )
  149. {
  150. delete mKeyList.front();
  151. mKeyList.pop_front();
  152. mCount--;
  153. }
  154. }
  155. void forgetKey( TKey key )
  156. {
  157. TKeyUseTrackerNode *node = removeNode( key );
  158. if( node )
  159. {
  160. delete node;
  161. }
  162. }
  163. U32 getUseCount( TKey key )
  164. {
  165. TKeyUseTrackerNode *node = findNode( key );
  166. if( node )
  167. {
  168. return node->mUseCount;
  169. }
  170. return 0;
  171. }
  172. U64 getTimeSinceUse( TKey key )
  173. {
  174. TKeyUseTrackerNode *node = findNode( key );
  175. if( node )
  176. {
  177. U64 now = getTime();
  178. U64 delta = now - node->mLastUse;
  179. return (U32)( delta / 1000000 );
  180. }
  181. return 0;
  182. }
  183. TData *getLastUseData( TKey key )
  184. {
  185. TKeyUseTrackerNode *node = findNode( key );
  186. if( node )
  187. {
  188. return &node->mData;
  189. }
  190. return NULL;
  191. }
  192. U32 getKeyCount()
  193. {
  194. return mCount;
  195. }
  196. };
  197. #endif