Created
July 8, 2022 02:12
-
-
Save tkersey/46489cef0b91522ee6658b03d91684c8 to your computer and use it in GitHub Desktop.
Reducing stack costs of structs by using Copy on Write (CoW)
This file contains 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
@propertyWrapper | |
struct CopyOnWriteBox<Value> { | |
private var ref: Ref<Value> | |
init(wrappedValue: Value) { | |
self.ref = Ref(wrappedValue) | |
} | |
var wrappedValue: Value { | |
get { | |
ref.value | |
} | |
set { | |
if isKnownUniquelyReferenced(&ref) { | |
ref.value = newValue | |
} else { | |
ref = Ref(newValue) | |
} | |
} | |
} | |
private final class Ref<T> { | |
var value: T | |
init(_ value: T) { | |
self.value = value | |
} | |
} | |
} | |
extension CopyOnWriteBox: Equatable where Value: Equatable { | |
static func == (lhs: Self<Value>, rhs: Self<Value>) -> Bool { | |
lhs.ref.value == rhs.ref.value | |
} | |
} |
This file contains 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
@dynamicMemberLookup | |
struct CoW<T> { | |
init(_ value: T) { | |
_storage = Storage(value) | |
} | |
public subscript<V>(dynamicMember keyPath: WritableKeyPath<T, V>) -> V { | |
get { value[keyPath: keyPath] } | |
set { value[keyPath: keyPath] = newValue } | |
} | |
var value: T { | |
get { | |
return _storage.value | |
} | |
set { | |
if isKnownUniquelyReferenced(&_storage) { | |
_storage.value = value | |
} else { | |
_storage = Storage(newValue) | |
} | |
} | |
} | |
private var _storage: Storage<T> | |
private class Storage<T> { | |
var value: T | |
init(_ value: T) { | |
self.value = value | |
} | |
} | |
} | |
extension CoW: Equatable where T: Equatable { | |
static func == (lhs: CoW<T>, rhs: CoW<T>) -> Bool { | |
return lhs.value == rhs.value | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment