Plusieurs propriétaires pour une donnée — tant qu'il en reste un, elle vit.Several owners for one piece of data — as long as one remains, it lives.
Box a déporté la donnée sur le tas sans toucher à la règle d'or : un seul propriétaire. Mais certaines structures ne sont pas des arbres. Un graphe où deux nœuds pointent le même voisin ; un cache qu'un service et son journal consultent tous deux ; une donnée dont on ne sait pas, à la compilation, qui la libérera en dernier. L'arbre du Vol 1 ne peut pas l'exprimer — il faudrait deux parents pour une même donnée. Rc<T> (reference counted) lève cette limite : il autorise plusieurs propriétaires d'une même valeur, et tient un compteur de ceux-ci. Chaque clone l'incrémente, chaque destruction le décrémente, et la donnée est libérée quand il atteint zéro. La possession unique devient une possession partagée — comptée.Box relocated the data to the heap without touching the golden rule: a single owner. But some structures aren't trees. A graph where two nodes point at the same neighbor; a cache that a service and its logger both consult; data where you can't tell, at compile time, who will free it last. Vol 1's tree can't express it — it would need two parents for one piece of data. Rc<T> (reference counted) lifts that limit: it allows several owners of one value, and keeps a count of them. Each clone increments it, each destruction decrements it, and the data is freed when it reaches zero. Single ownership becomes shared ownership — counted.
use std::rc::Rc; let donnee = Rc::new(Config { /* ... */ }); // compteur = 1 let a = Rc::clone(&donnee); // compteur = 2 — PAS une copie let b = Rc::clone(&donnee); // compteur = 3 // trois propriétaires, une seule donnée sur le tas. // elle vit tant qu'il reste au moins un Rc ; libérée quand le compteur tombe à 0. println!("propriétaires : {}", Rc::strong_count(&donnee)); // 3
Chaque Rc est un propriétaire à part entière : aucun n'est « le vrai », aucun n'est un simple emprunt. Ils pointent tous la même valeur sur le tas, à côté de laquelle vit un compteur. Tant que ce compteur est positif, la donnée existe ; le dernier Rc à disparaître la fait passer à zéro, et c'est lui qui déclenche la libération. Personne n'a à savoir qui sera le dernier — le comptage le détermine à l'exécution. C'est exactement ce que l'arbre à propriétaire unique ne pouvait pas faire.Each Rc is a full owner: none is 'the real one', none is a mere borrow. They all point at the same heap value, beside which lives a counter. As long as that counter is positive, the data exists; the last Rc to disappear brings it to zero, and it triggers the free. No one needs to know who'll be last — the count determines it at runtime. That's exactly what the single-owner tree couldn't do.
« Cette donnée a-t-elle vraiment plusieurs propriétaires, ou un seul avec des vues temporaires ? » Des emprunts (&T) suffisent si un propriétaire clair survit aux vues. Rc ne se justifie que lorsqu'aucun propriétaire unique ne se dégage — quand plusieurs parties doivent garder la donnée en vie, indépendamment les unes des autres.'Does this data really have several owners, or one with temporary views?' Borrows (&T) suffice if a clear owner outlives the views. Rc is justified only when no single owner emerges — when several parts must keep the data alive, independently of one another.
Rc n'est pas partageable entre threads : son compteur est une variable ordinaire, qu'incrémenter depuis deux threads à la fois corromprait. Pour le partage entre threads, il existe Arc (atomically reference counted), au compteur atomique — le sujet de la mécanique, plus loin. Le compilateur t'empêche de te tromper : un Rc envoyé à un autre thread ne compile pas. Choisir le bon, c'est répondre à une question — un thread, ou plusieurs ?Rc isn't shareable across threads: its counter is an ordinary variable, which incrementing from two threads at once would corrupt. For cross-thread sharing there's Arc (atomically reference counted), with an atomic counter — the mechanics' subject, further on. The compiler stops you from getting it wrong: an Rc sent to another thread won't compile. Choosing the right one answers a question — one thread, or several?