78 votes

Besoin d'une explication holistique sur les types comptés de cellules et de références de Rust

Il existe plusieurs types wrapper dans la Rouille de la bibliothèque standard:

Si je comprends bien, ce sont des wrappers qui offrent plus de possibilités que d'une simple référence. Alors que je comprends que certaines notions de base, je ne vois pas l'image entière.

Que font-ils exactement? Les cellules de référence et comptés par les familles orthogonales ou des fonctions similaires?

149voto

Matthieu M. Points 101624

Il y a deux concepts essentiels à la Rouille:

  • La propriété,
  • La mutabilité.

Les différents types pointeur (Box, Rc, Arc) sont concernés par la Propriété: ils permettent de contrôler si il y a un seul ou plusieurs propriétaires pour un seul objet.

D'autre part, les différentes cellules (Cell, RefCell, Mutex, RwLock, AtomicXXX) sont concernés par la Mutabilité.


Le fondateur de la règle de la Rouille est la sécurité de l'Aliasing XOR de la Mutabilité. C'est, un objet ne peut être muté en toute sécurité si il n'y a aucune référence à son intérieur.

Cette règle est généralement appliquée au moment de la compilation par les emprunter checker:

  • si vous avez un &T, vous ne pouvez pas avoir un &mut T pour le même objet dans le champ d'application,
  • si vous avez un &mut T, vous ne pouvez faire aucune référence à un même objet dans le champ d'application.

Cependant, parfois, ce n'est pas assez souple. Parfois vous avez besoin (ou envie) la possibilité d'avoir plusieurs références pour le même objet, et encore pour les transformer. Entrer dans les cellules.

L'idée d' Cell et RefCell , est de permettre la mutabilité dans la présence d'aliasing , de façon contrôlée:

  • Cell empêche la formation de référence à l'intérieur, en évitant balançant des références,
  • RefCell de quarts de l'application de la loi de l'Aliasing XOR de la Mutabilité de la compilation à l'exécution.

Cette fonctionnalité est parfois décrit comme fournissant de l'intérieur de la mutabilité, c'est là un objet qui, autrement, semble immuable de l'extérieur (&T) peut effectivement être muté.

Lorsque cette mutabilité s'étend sur plusieurs threads, vous finirez par utiliser Mutex, RwLock ou AtomicXXX; ils fournissent les mêmes fonctionnalités:

  • AtomicXXX sont juste Cell: pas de référence à l'intérieur, il suffit de le déplacer dans/out,
  • RwLock est juste RefCell: peut obtenir des références à l'intérieur, par les gardes,
  • Mutex est une version simplifiée de l' RwLock qui ne fait pas de distinction entre une lecture seule de la garde et de l'écriture de la garde; donc conceptuellement similaire à un RefCell avec seulement un borrow_mut méthode.

Si vous venez d'un C++ arrière-plan:

  • Box est unique_ptr,
  • Arc est shared_ptr,
  • Rc non thread-safe version de shared_ptr.

Et les cellules de fournir des fonctionnalités similaires mutable, sauf avec des garanties supplémentaires pour éviter l'aliasing questions; penser de l' Cell comme std::atomic et RefCell non thread-safe version de std::shared_mutex (ce qui jette au lieu de le bloquer si le verrou est pris).

22voto

Boiethios Points 8881

Merci à Matthieu de la bonne réponse, voici un schéma pour aider les gens à trouver le wrapper dont ils ont besoin:

+-----------+
| Ownership |
+--+--------+                              +================+
   |                         +-Static----->| T              |(1)
   |                         |             +================+
   |                         |
   |                         |             +================+
   |          +-----------+  | Local    Val| Cell<T>        |(1)
   +-Unique-->| Borrowing +--+-Dynamic---->|----------------|
   |          +-----------+  |          Ref| RefCell<T>     |(1)
   |                         |             +================+
   |                         |
   |                         |             +================+
   |                         | Threaded    | AtomicT        |(2)
   |                         +-Dynamic---->|----------------|
   |                                       | Mutex<T>       |(1)
   |                                       | RwLock<T>      |(1)
   |                                       +================+
   |
   |
   |                                       +================+
   |                         +-No--------->| Rc<T>          |
   |                         |             +================+
   | Locally  +-----------+  |
   +-Shared-->| Mutable?  +--+             +================+
   |          +-----------+  |          Val| Rc<Cell<T>>    |
   |                         +-Yes-------->|----------------|
   |                                    Ref| Rc<RefCell<T>> |
   |                                       +================+
   |
   |
   |                                       +================+
   |                         +-No--------->| Arc<T>         |
   |                         |             +================+
   | Shared   +-----------+  |
   +-Between->| Mutable?  +--+             +================+
     Threads  +-----------+  |             | Arc<AtomicT>   |(2)
                             +-Yes-------->|----------------|
                                           | Arc<Mutex<T>>  |
                                           | Arc<RwLock<T>> |
                                           +================+
  1. Dans ces cas, T peut être remplacé par Box<T>
  2. Utiliser AtomicT lorsque T est bool ou un numéro de

Pour savoir si vous devez utiliser Mutex ou RwLock, voir cette question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X