Skip to content

Instantly share code, notes, and snippets.

@janodev
Created May 1, 2016 11:05
Show Gist options
  • Save janodev/87bdf6fd94102012614444db97ca7567 to your computer and use it in GitHub Desktop.
Save janodev/87bdf6fd94102012614444db97ca7567 to your computer and use it in GitHub Desktop.
Throttling queue. Useful to discard button clicks until the button action is done executing.
import Foundation
/*
Execute asynchronous tasks concurrently until reaching a given 'max' number.
Tasks queued while there is already a 'max' number of concurrent tasks are silently discarded.
Usage: ThrottledQueue(1).queueAction { finish in /* work */ finish() }
*/
struct ThrottledQueue
{
private let semaphore: dispatch_semaphore_t
private let queue: dispatch_queue_t = dispatch_queue_create("com.yourcompany.ThrottledQueue", nil)
init(concurrentJobs:Int){
semaphore = dispatch_semaphore_create(concurrentJobs)
}
/* The action queued must call completion when it's done processing. */
func queueAction(action:(completion:()->())->())
{
if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) {
dispatch_async(queue){
action(){
dispatch_semaphore_signal(self.semaphore)
}
}
}
}
}
let queue = ThrottledQueue(concurrentJobs:2)
queue.queueAction { finish in print("1"); finish() }
queue.queueAction { finish in print("2"); finish() }
queue.queueAction { finish in print("3"); finish() } // discarded
// wait 2 seconds
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate:NSDate(timeIntervalSinceNow:2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment