/// <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();
        }