Hi there,
I just can’t get my head around mutable views and COW.
Here is a small example:
final class Storage {
var keys: [String] = []
var values: [Int] = []
}
public struct Document {
var _storageReference: Storage
public init() {
self._storageReference = Storage()
}
public init(_ values: DocumentValues) {
self._storageReference = values._storageReference
}
public var values: DocumentValues {
get { return DocumentValues(self) }
set { self = Document(newValue) }
}
}
public struct DocumentValues : MutableCollection {
unowned var _storageReference: Storage
init(_ document: Document) {
self._storageReference = document._storageReference
}
public var startIndex: Int {
return self._storageReference.keys.startIndex
}
public var endIndex: Int {
return self._storageReference.keys.endIndex
}
public func index(after i: Int) -> Int {
return self._storageReference.keys.index(after: i)
}
public subscript(position: Int) -> Int {
get { return _storageReference.values[position] }
set { self._storageReference.values[position] = newValue } // That will
break COW
}
}
First of all the _storageReference property is unowned because I wanted to
check the following:
var document = Document()
print(CFGetRetainCount(document._storageReference)) //=> 2
print(isKnownUniquelyReferenced(&document._storageReference)) // true
var values = document.values
print(CFGetRetainCount(values._storageReference)) //=> 2
print(isKnownUniquelyReferenced(&values._storageReference)) // false
Why is the second check false, even if the property is marked as unowned for
the view?
Next up, I don’t have an idea how to correctly COW optimize this view. Assume
the following scenario:
Scenario A:
var document = Document()
// just assume we already added some values and can mutate safely on a given
index
// mutation in place
document.values[0] = 10
VS:
Scenario B:
var document = Document()
let copy = document
// just assume we already added some values and can mutate safely on a given
index
// mutation in place
document.values[0] = 10 // <--- this should only mutate `document` but not
`copy`
We could change the subscript setter on the mutable view like this:
set {
if !isKnownUniquelyReferenced(&self._storageReference) {
self._storageReference = ... // clone
}
self._storageReference.values[position] = newValue
}
There is only one problem here. We’d end up cloning the storage every time,
because as shown in the very first example, even with unowned the function
isKnownUniquelyReferenced will return false for scenario A.
Any suggestions?
PS: In general I also wouldn’t want to use unowned because the view should be
able to outlive it’s parent.
--
Adrian Zubarev
Sent with Airmail
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users