È più facile implementare la copia su scrittura in un linguaggio orientato agli oggetti, come C++. Ad esempio, la maggior parte delle classi contenitore in Qt sono copy-on-write.
Ma se lo si può fare anche in C, è solo un po 'più di lavoro. Quando si desidera assegnare i dati a un nuovo blocco di dati, non si esegue una copia, ma si copia semplicemente un puntatore in un intreccio di wrapper attorno ai dati. È necessario tenere traccia dei blocchi di dati dello stato dei dati. Se ora modifichi qualcosa nel tuo nuovo blocco dati, fai una copia "reale" e cambia lo stato. Ovviamente non è più possibile utilizzare gli operatori semplici come "=" per l'assegnazione, ma è necessario avere funzioni (in C++ si farebbe semplicemente un sovraccarico dell'operatore).
Un'implementazione più robusta dovrebbe utilizzare i contatori di riferimento invece di una semplice bandiera, lascio a voi.
Un esempio veloce e sporco: Se si dispone di un
struct big {
//lots of data
int data[BIG_NUMBER];
}
è necessario implementare le funzioni di assegnare e getter/setter te stesso.
// assume you want to implent cow for a struct big of some kind
// now instead of
struct big a, b;
a = b;
a.data[12345] = 6789;
// you need to use
struct cow_big a,b;
assign(&a, b); //only pointers get copied
set_some_data(a, 12345, 6789); // now the stuff gets really copied
//the basic implementation could look like
struct cow_big {
struct big *data;
int needs_copy;
}
// shallow copy, only sets a pointer.
void assign(struct cow_big* dst, struct cow_big src) {
dst->data = src.data;
dst->needs_copy = true;
}
// change some data in struct big. if it hasn't made a deep copy yet, do it here.
void set_some_data(struct cow_big* dst, int index, int data } {
if (dst->needs_copy) {
struct big* src = dst->data;
dst->data = malloc(sizeof(big));
*(dst->data) = src->data; // now here is the deep copy
dst->needs_copy = false;
}
dst->data[index] = data;
}
È necessario scrivere anche costruttori e distruttori. Consiglio vivamente C++ per questo.
Che tipo di dati stai copiando?Copy-on-write potrebbe non essere l'unica soluzione. –