public
Last active

Groovy implementation (untested) for Cedric's SlidingWindowMap

  • Download Gist
gistfile1.groovy
Groovy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.ArrayBlockingQueue
 
public class SlidingWindowMap
{
def queue
def periodMs
 
public SlidingWindowMap(Set<String> keys, int maxCount, long periodMs)
{
queue = new PriorityBlockingQueue(keys.size(), { a, b -> (a[1].size() <=> b[1].size()) ?: (a[1].peek() <=> b[1].peek()) } as Comparator)
 
queue.addAll(keys.collect { [it, new ArrayBlockingQueue<Long>(maxCount)] })
 
this.periodMs = periodMs
}
 
/**
* @return a key that has been used less than `maxCount` times during the
* past `periodMs` milliseconds or null if no such key exists.
*/
public String getNextKey()
{
// Get the least used key with oldest usage.
def keyrec = queue.poll()
 
if (keyrec) {
ArrayBlockingQueue<Long> uses = keyrec[1]
 
// Expire uses earlier than the time window.
while (uses.size() && uses.peek() < System.currentTimeMillis() - periodMs) {
uses.take()
}
 
// Try to add the timestamp for this usage.
def useable = uses.offer(System.currentTimeMillis())
 
// Put the keyrec back into the queue.
queue.add(keyrec)
 
if (useable) return keyrec[0]
}
 
return null
}
 
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.