/// <summary>Decay the stored counts for each user and clean as necessary.</summary> /// <remarks> /// Decay the stored counts for each user and clean as necessary. /// This method should be called periodically in order to keep /// counts current. /// </remarks> private void DecayCurrentCounts() { long total = 0; IEnumerator <KeyValuePair <object, AtomicLong> > it = callCounts.GetEnumerator(); while (it.HasNext()) { KeyValuePair <object, AtomicLong> entry = it.Next(); AtomicLong count = entry.Value; // Compute the next value by reducing it by the decayFactor long currentValue = count.Get(); long nextValue = (long)(currentValue * decayFactor); total += nextValue; count.Set(nextValue); if (nextValue == 0) { // We will clean up unused keys here. An interesting optimization might // be to have an upper bound on keyspace in callCounts and only // clean once we pass it. it.Remove(); } } // Update the total so that we remain in sync totalCalls.Set(total); // Now refresh the cache of scheduling decisions RecomputeScheduleCache(); }