> On 18 Nov 2016, at 13:05, Adrian Zubarev via swift-users
> <swift-users@swift.org> wrote:
>
> 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
> swift-users@swift.org <mailto:swift-users@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users
> <https://lists.swift.org/mailman/listinfo/swift-users>
This is kind of an invalid/unsafe design IMO; DocumentValues may escape the
scope of the Document and the underlying storage may be deallocated.
Instead, I’d recommend a function:
func withDocumentValues<T>(_ invoke: (inout DocumentValues)->T) -> T {
var view = DocumentValues(self)
defer { _fixLifetime(view) }
return invoke(&view)
}
(unfortunately, this isn’t completely safe because somebody could still copy
the DocumentValues from their closure, the same way you can copy the pointer
from String’s withCString, but that’s a limitation of Swift right now)
CC: John McCall, because I read his suggestion in the thread about contiguous
memory/borrowing that we could have a generalised @noescape. In this example,
you would want the DocumentValues parameter in the closure to be @noescape.
- Karl
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users