aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llkeythrottle.h
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llcommon/llkeythrottle.h')
-rw-r--r--linden/indra/llcommon/llkeythrottle.h110
1 files changed, 79 insertions, 31 deletions
diff --git a/linden/indra/llcommon/llkeythrottle.h b/linden/indra/llcommon/llkeythrottle.h
index 8314269..eb1519a 100644
--- a/linden/indra/llcommon/llkeythrottle.h
+++ b/linden/indra/llcommon/llkeythrottle.h
@@ -55,33 +55,40 @@ class LLKeyThrottleImpl
55protected: 55protected:
56 struct Entry { 56 struct Entry {
57 U32 count; 57 U32 count;
58 BOOL blocked; 58 bool blocked;
59 59
60 Entry() : count(0), blocked(FALSE) { } 60 Entry() : count(0), blocked(false) { }
61 }; 61 };
62 62
63 typedef std::map<T, Entry> EntryMap; 63 typedef std::map<T, Entry> EntryMap;
64 64
65 EntryMap * prevMap; 65 EntryMap* prevMap;
66 EntryMap * currMap; 66 EntryMap* currMap;
67 67
68 U32 countLimit; 68 U32 countLimit;
69 // maximum number of keys allowed per interval 69 // maximum number of keys allowed per interval
70 70
71 U64 interval_usec; 71 U64 intervalLength; // each map covers this time period (usec or frame number)
72 // each map covers this time period 72 U64 startTime; // start of the time period (usec or frame number)
73 U64 start_usec;
74 // currMap started counting at this time 73 // currMap started counting at this time
75 // prevMap covers the previous interval 74 // prevMap covers the previous interval
76 75
77 LLKeyThrottleImpl() : prevMap(0), currMap(0), 76 LLKeyThrottleImpl() :
78 countLimit(0), interval_usec(0), 77 prevMap(NULL),
79 start_usec(0) { }; 78 currMap(NULL),
79 countLimit(0),
80 intervalLength(1),
81 startTime(0)
82 {}
80 83
81 static U64 getTime() 84 static U64 getTime()
82 { 85 {
83 return LLFrameTimer::getTotalTime(); 86 return LLFrameTimer::getTotalTime();
84 } 87 }
88 static U64 getFrame() // Return the current frame number
89 {
90 return (U64) LLFrameTimer::getFrameCount();
91 }
85}; 92};
86 93
87 94
@@ -89,17 +96,12 @@ template< class T >
89class LLKeyThrottle 96class LLKeyThrottle
90{ 97{
91public: 98public:
92 LLKeyThrottle(U32 limit, F32 interval) 99 // @param realtime = FALSE for frame-based throttle, TRUE for usec
100 // real-time throttle
101 LLKeyThrottle(U32 limit, F32 interval, BOOL realtime = TRUE)
93 : m(* new LLKeyThrottleImpl<T>) 102 : m(* new LLKeyThrottleImpl<T>)
94 { 103 {
95 // limit is the maximum number of keys 104 setParameters( limit, interval, realtime );
96 // allowed per interval (in seconds)
97 m.countLimit = limit;
98 m.interval_usec = (U64)(interval * USEC_PER_SEC);
99 m.start_usec = LLKeyThrottleImpl<T>::getTime();
100
101 m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
102 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
103 } 105 }
104 106
105 ~LLKeyThrottle() 107 ~LLKeyThrottle()
@@ -118,18 +120,26 @@ public:
118 // call each time the key wants use 120 // call each time the key wants use
119 State noteAction(const T& id, S32 weight = 1) 121 State noteAction(const T& id, S32 weight = 1)
120 { 122 {
121 U64 now = LLKeyThrottleImpl<T>::getTime(); 123 U64 now = 0;
124 if ( mIsRealtime )
125 {
126 now = LLKeyThrottleImpl<T>::getTime();
127 }
128 else
129 {
130 now = LLKeyThrottleImpl<T>::getFrame();
131 }
122 132
123 if (now >= (m.start_usec + m.interval_usec)) 133 if (now >= (m.startTime + m.intervalLength))
124 { 134 {
125 if (now < (m.start_usec + 2 * m.interval_usec)) 135 if (now < (m.startTime + 2 * m.intervalLength))
126 { 136 {
127 // prune old data 137 // prune old data
128 delete m.prevMap; 138 delete m.prevMap;
129 m.prevMap = m.currMap; 139 m.prevMap = m.currMap;
130 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap; 140 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
131 141
132 m.start_usec += m.interval_usec; 142 m.startTime += m.intervalLength;
133 } 143 }
134 else 144 else
135 { 145 {
@@ -139,12 +149,12 @@ public:
139 m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap; 149 m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
140 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap; 150 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
141 151
142 m.start_usec = now; 152 m.startTime = now;
143 } 153 }
144 } 154 }
145 155
146 U32 prevCount = 0; 156 U32 prevCount = 0;
147 BOOL prevBlocked = FALSE; 157 bool prevBlocked = false;
148 158
149 typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id); 159 typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
150 if (prev != m.prevMap->end()) 160 if (prev != m.prevMap->end())
@@ -166,7 +176,7 @@ public:
166 // (now) time. 176 // (now) time.
167 177
168 // compute current, windowed rate 178 // compute current, windowed rate
169 F64 timeInCurrent = ((F64)(now - m.start_usec) / m.interval_usec); 179 F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
170 F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent); 180 F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
171 181
172 curr.blocked |= averageCount > m.countLimit; 182 curr.blocked |= averageCount > m.countLimit;
@@ -193,17 +203,17 @@ public:
193 noteAction(id); 203 noteAction(id);
194 typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id]; 204 typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
195 curr.count = llmax(m.countLimit, curr.count); 205 curr.count = llmax(m.countLimit, curr.count);
196 curr.blocked = TRUE; 206 curr.blocked = true;
197 } 207 }
198 208
199 // returns TRUE if key is blocked 209 // returns true if key is blocked
200 BOOL isThrottled(const T& id) const 210 bool isThrottled(const T& id) const
201 { 211 {
202 if (m.currMap->empty() 212 if (m.currMap->empty()
203 && m.prevMap->empty()) 213 && m.prevMap->empty())
204 { 214 {
205 // most of the time we'll fall in here 215 // most of the time we'll fall in here
206 return FALSE; 216 return false;
207 } 217 }
208 218
209 // NOTE, we ignore the case where id is in the map but the map is stale. 219 // NOTE, we ignore the case where id is in the map but the map is stale.
@@ -221,11 +231,49 @@ public:
221 { 231 {
222 return entry->second.blocked; 232 return entry->second.blocked;
223 } 233 }
224 return FALSE; 234 return false;
235 }
236
237 // Get the throttling parameters
238 void getParameters( U32 & out_limit, F32 & out_interval, BOOL & out_realtime )
239 {
240 out_limit = m.countLimit;
241 out_interval = m.intervalLength;
242 out_realtime = mIsRealtime;
243 }
244
245 // Set the throttling behavior
246 void setParameters( U32 limit, F32 interval, BOOL realtime )
247 {
248 // limit is the maximum number of keys
249 // allowed per interval (in seconds or frames)
250 mIsRealtime = realtime;
251 m.countLimit = limit;
252 if ( mIsRealtime )
253 {
254 m.intervalLength = (U64)(interval * USEC_PER_SEC);
255 m.startTime = LLKeyThrottleImpl<T>::getTime();
256 }
257 else
258 {
259 m.intervalLength = (U64)interval;
260 m.startTime = LLKeyThrottleImpl<T>::getFrame();
261 }
262
263 if ( m.intervalLength == 0 )
264 { // Don't allow zero intervals
265 m.intervalLength = 1;
266 }
267
268 delete m.prevMap;
269 m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
270 delete m.currMap;
271 m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
225 } 272 }
226 273
227protected: 274protected:
228 LLKeyThrottleImpl<T>& m; 275 LLKeyThrottleImpl<T>& m;
276 BOOL mIsRealtime; // TRUE to be time based (default), FALSE for frame based
229}; 277};
230 278
231#endif 279#endif