diff options
Diffstat (limited to 'linden/indra/llcommon/llkeythrottle.h')
-rw-r--r-- | linden/indra/llcommon/llkeythrottle.h | 110 |
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 | |||
55 | protected: | 55 | protected: |
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 > | |||
89 | class LLKeyThrottle | 96 | class LLKeyThrottle |
90 | { | 97 | { |
91 | public: | 98 | public: |
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 | ||
227 | protected: | 274 | protected: |
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 |