00001
00032 #ifndef LL_KEYUSETRACKER_H
00033 #define LL_KEYUSETRACKER_H
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 template <class TKey, class TData>
00045 class KeyUseTrackerNodeImpl
00046 {
00047 public:
00048 U64 mLastUse;
00049 U32 mUseCount;
00050 TKey mKey;
00051 TData mData;
00052
00053 KeyUseTrackerNodeImpl( TKey k, TData d ) :
00054 mLastUse(0),
00055 mUseCount(0),
00056 mKey( k ),
00057 mData( d )
00058 {
00059 }
00060 };
00061
00062
00063 template <class TKey, class TData>
00064 class LLKeyUseTracker
00065 {
00066 typedef KeyUseTrackerNodeImpl<TKey,TData> TKeyUseTrackerNode;
00067 typedef std::list<TKeyUseTrackerNode *> TKeyList;
00068 TKeyList mKeyList;
00069 U64 mMemUsecs;
00070 U64 mLastExpire;
00071 U32 mMaxCount;
00072 U32 mCount;
00073
00074 static U64 getTime()
00075 {
00076
00077
00078
00079 return LLFrameTimer::getTotalTime();
00080 }
00081
00082 void ageKeys()
00083 {
00084 U64 now = getTime();
00085 if( now == mLastExpire )
00086 {
00087 return;
00088 }
00089 mLastExpire = now;
00090
00091 while( !mKeyList.empty() && (now - mKeyList.front()->mLastUse > mMemUsecs ) )
00092 {
00093 delete mKeyList.front();
00094 mKeyList.pop_front();
00095 mCount--;
00096 }
00097 }
00098
00099 TKeyUseTrackerNode *findNode( TKey key )
00100 {
00101 ageKeys();
00102
00103 typename TKeyList::iterator i;
00104 for( i = mKeyList.begin(); i != mKeyList.end(); i++ )
00105 {
00106 if( (*i)->mKey == key )
00107 return *i;
00108 }
00109
00110 return NULL;
00111 }
00112
00113 TKeyUseTrackerNode *removeNode( TKey key )
00114 {
00115 TKeyUseTrackerNode *i;
00116 i = findNode( key );
00117 if( i )
00118 {
00119 mKeyList.remove( i );
00120 mCount--;
00121 return i;
00122 }
00123
00124 return NULL;
00125 }
00126
00127 public:
00128 LLKeyUseTracker( U32 memory_seconds, U32 max_count ) :
00129 mLastExpire(0),
00130 mMaxCount( max_count ),
00131 mCount(0)
00132 {
00133 mMemUsecs = ((U64)memory_seconds) * 1000000;
00134 }
00135
00136 ~LLKeyUseTracker()
00137 {
00138
00139 while( !mKeyList.empty() )
00140 {
00141 delete mKeyList.front();
00142 mKeyList.pop_front();
00143 mCount--;
00144 }
00145 }
00146
00147 void markUse( TKey key, TData data )
00148 {
00149 TKeyUseTrackerNode *node = removeNode( key );
00150 if( !node )
00151 {
00152 node = new TKeyUseTrackerNode(key, data);
00153 }
00154 else
00155 {
00156
00157 node->mData = data;
00158 }
00159 node->mLastUse = getTime();
00160 node->mUseCount++;
00161 mKeyList.push_back( node );
00162 mCount++;
00163
00164
00165 if( mCount > mMaxCount )
00166 {
00167 delete mKeyList.front();
00168 mKeyList.pop_front();
00169 mCount--;
00170 }
00171 }
00172
00173 void forgetKey( TKey key )
00174 {
00175 TKeyUseTrackerNode *node = removeNode( key );
00176 if( node )
00177 {
00178 delete node;
00179 }
00180 }
00181
00182 U32 getUseCount( TKey key )
00183 {
00184 TKeyUseTrackerNode *node = findNode( key );
00185 if( node )
00186 {
00187 return node->mUseCount;
00188 }
00189 return 0;
00190 }
00191
00192 U64 getTimeSinceUse( TKey key )
00193 {
00194 TKeyUseTrackerNode *node = findNode( key );
00195 if( node )
00196 {
00197 U64 now = getTime();
00198 U64 delta = now - node->mLastUse;
00199 return (U32)( delta / 1000000 );
00200 }
00201 return 0;
00202 }
00203
00204 TData *getLastUseData( TKey key )
00205 {
00206 TKeyUseTrackerNode *node = findNode( key );
00207 if( node )
00208 {
00209 return &node->mData;
00210 }
00211 return NULL;
00212 }
00213
00214 U32 getKeyCount()
00215 {
00216 return mCount;
00217 }
00218 };
00219
00220 #endif