Last active
April 11, 2021 16:20
-
-
Save atierian/1cb38e56c68edabe07c9f019a4e06eb9 to your computer and use it in GitHub Desktop.
Struct with copy on write semantics
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
| struct Person { | |
| fileprivate final class Storage { | |
| var name: String | |
| var age: UInt8 | |
| init(name: String, age: UInt8) { | |
| self.name = name | |
| self.age = age | |
| } | |
| } | |
| private var storage: Storage | |
| init(name: String, age: UInt8) { | |
| storage = .init(name: name, age: age) | |
| } | |
| } | |
| extension Person.Storage { | |
| func copy() -> Person.Storage { | |
| .init(name: name, age: age) | |
| } | |
| } | |
| extension Person { | |
| private var storageForWriting: Person.Storage { | |
| mutating get { | |
| if !isKnownUniquelyReferenced(&storage) { | |
| storage = storage.copy() | |
| } | |
| return storage | |
| } | |
| } | |
| var name: String { | |
| get { storage.name } | |
| set { storageForWriting.name = newValue } | |
| } | |
| var age: UInt8 { | |
| get { storage.age } | |
| set { storageForWriting.age = newValue } | |
| } | |
| } | |
| // Protocol | |
| protocol Storageable: AnyObject { | |
| func copy() -> Self | |
| } | |
| protocol CopyOnWriteable { | |
| associatedtype Storage: Storageable | |
| var storage: Storage { get set } | |
| var storageForWriting: Storage { mutating get } | |
| } | |
| extension CopyOnWriteable { | |
| var storageForWriting: Storage { | |
| mutating get { | |
| if !isKnownUniquelyReferenced(&storage) { | |
| storage = storage.copy() | |
| } | |
| return storage | |
| } | |
| } | |
| } | |
| struct Car: CopyOnWriteable { | |
| typealias Storage = CarStorage | |
| final class CarStorage: Storageable { | |
| var year: UInt | |
| var color: String | |
| func copy() -> Self { | |
| .init(year: year, color: color) | |
| } | |
| init(year: UInt, color: String) { | |
| self.year = year | |
| self.color = color | |
| } | |
| } | |
| var storage: CarStorage | |
| init(year: UInt, color: String) { | |
| storage = .init(year: year, color: color) | |
| } | |
| var year: UInt { | |
| get { storage.year } | |
| set { storageForWriting.year = newValue } | |
| } | |
| var color: String { | |
| get { storage.color } | |
| set { storageForWriting.color = newValue } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment