@ GuardedBy ( "lock" ) private void cleanState ( ) { long eventTime = timeSource . get ( ) ; long bucketsToSkip = ( eventTime - headTime ) / window . getResolution ( ) ; while ( bucketsToSkip > 0 ) { headIndex = ( headIndex + 1 ) % interimValues . length ; bucketsToSkip -- ; overallValue -= interimValues [ headIndex ] ; interimValues [ headIndex ] = 0L ; headTime += window . getResolution ( ) ; } }
Clean out old data from the buckets getting us ready to enter a new bucket . interimValues headTime and headIndex comprise a circular buffer of the last n sub - values and the start time of the head bucket . On each write or get we progressively clear out entries in the circular buffer until headTime is within one tick of the current time ; we have then found the correct bucket .