Implement copy-on-write by hand for a type backed by a class buffer using isKnownUniquelyReferenced
Build a value type Box<T> whose storage is a class buffer, so copies stay shared until mutation.
Requirements:
- Assignment must be O(1) — share the buffer, do not copy the payload.
- A mutation must copy the buffer only when it is not uniquely referenced.
- Use
isKnownUniquelyReferencedto decide.
final class Buffer<T> { var value: T; init(_ v: T) { value = v } }
struct Box<T> {
private var buffer: Buffer<T>
init(_ v: T) { buffer = Buffer(v) }
var value: T {
get { buffer.value }
set {
// your code here: copy the buffer if it is shared, then write
}
}
}
Write the setter implementation.
Wrap a heap class buffer in a struct. Before each mutation, check isKnownUniquelyReferenced(&buffer); if false, replace it with a fresh deep copy, then write. A copy happens only when a shared buffer is mutated — lazy value semantics.
- ✗Copying the buffer on every assignment instead of only on shared mutation
- ✗Checking uniqueness in the getter rather than before a write
- ✗Thinking
isKnownUniquelyReferencedworks on value types orweakrefs
- →Why must the uniqueness check happen before the write, not after?
- →What breaks if two threads mutate the same shared buffer concurrently?
In the setter, check buffer uniqueness before writing. If it is shared, replace it with a fresh copy; otherwise write in place:
var value: T {
get { buffer.value }
set {
if !isKnownUniquelyReferenced(&buffer) {
buffer = Buffer(buffer.value) // detach the shared buffer
}
buffer.value = newValue
}
}
Assigning a Box copies only the reference to buffer — an O(1) operation. The first mutation of a shared buffer sees isKnownUniquelyReferenced == false and copies; afterwards the owner is unique and writes happen in place. Value semantics hold with no copy on reads.