Skip to content

Instantly share code, notes, and snippets.

@descorp
Last active September 14, 2020 22:25
Show Gist options
  • Select an option

  • Save descorp/8e8e403d0b626c542ff2f6bfdaace80a to your computer and use it in GitHub Desktop.

Select an option

Save descorp/8e8e403d0b626c542ff2f6bfdaace80a to your computer and use it in GitHub Desktop.
Lock + Timer
// Our server is calling the external API using call_api that is doing the HTTP
// call. The API provider charges us if we make more than 10 calls per second.
//
// How would you implement something that keeps us below the limit?
//: [Previous](@previous)
import Foundation
import PlaygroundSupport
var str = "Hello, playground"
final class Proxy {
private let limit: Int
init(limit: Int) {
self.limit = limit
}
private var isBusy = false
private var counter: Int = 0
private var tasks: [DispatchWorkItem] = []
private var runner = DispatchQueue(label: UUID().uuidString, attributes: .concurrent)
func process(_ caller: @escaping ()->()) {
tasks.append(DispatchWorkItem() { caller() })
run()
}
private func run() {
guard counter < limit else { return delay() }
while !tasks.isEmpty, counter < limit {
let task = tasks.removeFirst()
counter += 1
runner.async(execute: task)
}
delay()
}
private func delay() {
guard !isBusy else { return }
self.isBusy = true
runner.asyncAfter(deadline: .now() + .seconds(1), flags: .barrier) { [weak self] in
guard let self = self else { return }
self.counter = 0
self.isBusy = false
if !self.tasks.isEmpty { self.run() }
}
}
}
let proxy = Proxy(limit: 10)
for i in 0...99 {
proxy.process {
//DispatchQueue.main.async {
print("\(i) : \(Date())")
//}
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
//: [Next](@next)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment