Skip to content

Instantly share code, notes, and snippets.

@rbrovko
Forked from drewmccormack/LetTheCoWGo.swift
Created February 8, 2019 13:21
Show Gist options
  • Save rbrovko/1dced182d5a12b551442f34304e49af4 to your computer and use it in GitHub Desktop.
Save rbrovko/1dced182d5a12b551442f34304e49af4 to your computer and use it in GitHub Desktop.
Demonstrates how a Swift value constant can mutate when using Copy-on-Write (CoW) and multi-threading.
import Foundation
struct NuclearPowerStationOperator {
class Storage {
var turnOffCores: Bool = false
func copy() -> Storage {
let new = Storage()
new.turnOffCores = turnOffCores
return new
}
}
private var storage: Storage = Storage()
var turnOffCores: Bool {
get {
return storage.turnOffCores
}
set {
if isKnownUniquelyReferenced(&storage) {
Thread.sleep(forTimeInterval: 1.0) // Sleep to simulate race condition
storage.turnOffCores = newValue
} else {
storage = storage.copy()
storage.turnOffCores = newValue
}
}
}
var description: String {
return "\(turnOffCores ? "We are in danger" : "We are safe")"
}
}
// Create a mutable value
var crazyOperator = NuclearPowerStationOperator()
DispatchQueue.global(qos: .background).async {
Thread.sleep(forTimeInterval: 0.5) // Sleep a little to give main thread time to start setting property
let saneOperator = crazyOperator // Create a constant copy of the operator from main thread
print(saneOperator.description) // Print our intial property value
Thread.sleep(forTimeInterval: 2.0) // Simulate race by waiting for setter on main thread to finish
print(saneOperator.description) // Test property (it will be different)
}
// Update the value. Note that the setter simulates a race condition by being very slow
crazyOperator.turnOffCores = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment