Skip to content

Instantly share code, notes, and snippets.

@brennanMKE
Created November 5, 2019 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brennanMKE/6e6d1be169a9fff215570721fe74651d to your computer and use it in GitHub Desktop.
Save brennanMKE/6e6d1be169a9fff215570721fe74651d to your computer and use it in GitHub Desktop.

Spinlock

The Dispatch framework does not provide a spinlock, likely for good reason. Here a spinlock protocol and class implementation are defined with simple code. The Playground can be used to try it out.

There really is no good use for a spinlock given that Dispatch already allows for sync logic which handles locking and priority inversion concerns. While a spinlock is waiting with the sleep calls no other work can be done on the main queue. It is essentially the same as using sync to put work on another queue while locking the current queue as a consequence.


import Foundation
public class DispatchSpinlock: Spinlock {
private let sleepInterval: TimeInterval
private var isDone: Bool = false
private var timeout: DispatchTime = .distantFuture
private var isTimedOut: Bool {
let timedOut = DispatchTime.now() >= timeout
return timedOut
}
public init(sleepInterval: TimeInterval = 0.1) {
self.sleepInterval = sleepInterval
}
public func done() {
isDone = true
}
public func wait() {
wait(timeout: .distantFuture)
}
@discardableResult
public func wait(timeout: DispatchTime) -> DispatchTimeoutResult {
let result: DispatchTimeoutResult
self.timeout = timeout
while !isDone && !isTimedOut {
print("Spinning")
Thread.sleep(forTimeInterval: sleepInterval)
}
if isTimedOut {
result = .timedOut
} else {
result = .success
}
return result
}
}
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
print("Creating spinlock")
let spinlock = DispatchSpinlock(sleepInterval: 1.0)
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
spinlock.done()
}
print("Waiting...")
let result = spinlock.wait(timeout: .now() + 5.0)
print("Finished waiting...")
switch result {
case .success:
print("success")
case .timedOut:
print("timed out")
}
print("Done")
PlaygroundPage.current.finishExecution()
import Foundation
public protocol Spinlock {
func done()
func wait()
func wait(timeout: DispatchTime) -> DispatchTimeoutResult
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment