How can I make a container with copy-on-write semantics? (Swift)

孤者浪人 提交于 2020-01-20 04:20:05

问题


I have a very large structure, which I want to ensure is not copied needlessly. How can I make a copy-on-write container for it?


回答1:


A copy-on-write is usually a struct wrapper over some backing object.

public final class MutableHeapStore<T>: NonObjectiveCBase
{
    public typealias Storage = T

    public private(set) var storage: Storage

    public init(storage: Storage)
    {
        self.storage = storage
    }
}

public struct COW<T>
{
    public typealias Storage = MutableHeapStore<T>
    public typealias Value = T

    public var storage: Storage

    public init(storage: Storage)
    {
        self.storage = storage
    }

    public var value: Value
    {
        get
        {
            return storage.storage
        }

        set
        {
            if isUniquelyReferenced(&storage)
            {
                storage.storage = newValue
            }

            else
            {
                storage = Storage(storage: newValue)
            }
        }
    }

    public init(_ value: Value)
    {
        self.init(storage: Storage(storage: value))
    }
}

extension COW: CustomStringConvertible
{
    public var description: String
    {
        return String(value)
    }
}

The trick lies in asserting isUniquelyReferenced every time the boxed value is mutated. If the underlying storage object is singly referenced, nothing is to be done. However if another reference exists, one must create a new storage.

Is this code thread-safe? It is exactly as safe as any other value type, e.g. Int or Bool.




回答2:


Here's a bit simpler example.

struct COWExample1<T> {
    private var box = Box<[T]>(value: [T]())
    var count: Int {
        return box.value.count
    }
    mutating func append(e: T) {
        ensureBoxUniqueRefed()
        box.value.append(e)
    }
    private mutating func ensureBoxUniqueRefed() {
        if isUniquelyReferencedNonObjC(&box) == false {
            box = box.duplicated()
        }
    }
}

private final class Box<T> {
    var value: T
    init(value: T) {
        self.value = value
    }
    func duplicated() -> Box<T> {
        return Box(value: value)
    }
}



回答3:


The previous answers aren't wrong, but there's a much simpler way. The Swift team has a list of performance tips, and they say:

The easiest way to implement copy-on-write is to compose existing copy-on-write data structures, such as Array.

It doesn't get much simpler than that!



来源:https://stackoverflow.com/questions/32984258/how-can-i-make-a-container-with-copy-on-write-semantics-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!