Created
August 6, 2016 21:30
-
-
Save pixelspark/50afabc9ce29412cca7ef6d6323da7de to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Throttle wraps a block with throttling logic, guarantueeing that the block will never be called (by enquueing | |
asynchronously on `queue`) more than once each `interval` seconds. If the wrapper callback is called more than once | |
in an interval, it will use the most recent call's parameters when eventually calling the wrapped block (after `interval` | |
has elapsed since the last call to the wrapped function) - i.e. calls are not queued and may get 'lost' by being superseded | |
by a newer call. */ | |
public func throttle<P>(interval: TimeInterval, queue: DispatchQueue, _ block: ((P) -> ())) -> ((P) -> ()) { | |
var lastExecutionTime: TimeInterval? = nil | |
var scheduledExecutionParameters: P? = nil | |
let mutex = Mutex() | |
return { (p: P) -> () in | |
return mutex.locked { | |
let currentTime = NSDate.timeIntervalSinceReferenceDate | |
if let lastExecuted = lastExecutionTime { | |
if (currentTime - lastExecuted) > interval { | |
// Not the first execution, but the last execution was more than interval ago. Execute now. | |
lastExecutionTime = currentTime | |
queue.async { | |
block(p) | |
} | |
} | |
else { | |
// Last execution was less than interval ago | |
if scheduledExecutionParameters != nil { | |
// Another execution was already planned, just mae sure it will use latest parameters | |
scheduledExecutionParameters = p | |
} | |
else { | |
// Schedule execution | |
scheduledExecutionParameters = p | |
let scheduleDelay = lastExecuted + interval - currentTime | |
queue.asyncAfter(deadline: DispatchTime.now() + scheduleDelay) { | |
// Delayed execution | |
let p = mutex.locked { () -> P in | |
let params = scheduledExecutionParameters! | |
scheduledExecutionParameters = nil | |
return params | |
} | |
block(p) | |
} | |
} | |
} | |
} | |
else { | |
// First time this function is executed | |
lastExecutionTime = currentTime | |
queue.async { | |
block(p) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment