În Swift, colecțiile standard precum Array, Dictionary și Set oferă semantică pură de valoare (Value Semantics), dar fără costul copierii imediate a memoriei de fiecare dată când o colecție este transmisă unei funcții. Această magie este realizată prin Copy-on-Write (CoW).
Deși structurile definite de utilizator beneficiază automat de Value Semantics, compilatorul nu le atribuie automat comportament CoW dacă acestea conțin bucăți mari de memorie. Pentru structuri personalizate mari (containere grafice, matrici matematice, buffere de rețea), putem implementa CoW manual folosind o clasă internă de stocare și funcția standard isKnownUniquelyReferenced.
// 1. Clasa internă de stocare (Reference Type alocat pe Heap):
private final class StorageContainer<T> {
var elemente: [T]
init(elemente: [T]) {
self.elemente = elemente
}
func clona() -> StorageContainer<T> {
return StorageContainer(elemente: self.elemente)
}
}
// 2. Structura publică (Value Type vizibil dezvoltatorilor):
struct CoWVector<T> {
private var container: StorageContainer<T>
init(elemente: [T] = []) {
self.container = StorageContainer(elemente: elemente)
}
// Metodă mutatoare critică: verifică unicitatea referinței!
private mutating func asiguraStocareUnica() {
// isKnownUniquelyReferenced returnează true doar dacă contorul de referință ARC este exact 1!
if !isKnownUniquelyReferenced(&container) {
// Dacă buffer-ul este partajat cu alt vector, îl clonăm pe loc:
self.container = container.clona()
}
}
mutating func adauga(_ element: T) {
asiguraStocareUnica()
container.elemente.append(element)
}
var count: Int {
container.elemente.count
}
}
// 3. Testarea eficienței în practică:
var vectorOriginal = CoWVector(elemente: Array(repeating: 10, count: 1_000_000))
var vectorCopie = vectorOriginal
// zero copiere de date! Ambele structuri indică spre exact aceeași instanță de heap!
vectorCopie.adauga(99)
// Doar aici are loc clonarea fizică a buffer-ului, protejând 'vectorOriginal'!
Reguli Fundamentale pentru isKnownUniquelyReferenced
- Parametrul transmis trebuie să fie o referință directă
inoutla o variabilă de clasă (nu o proprietate calculată). - Dacă instanța este partajată sau este accesată concurent dintr-un alt fir, funcția va returna în siguranță
false, forțând clonarea și prevenind data races.